(强连通分量)[HAOI2006]受欢迎的牛

https://www.luogu.org/problemnew/show/P2341
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你算出有多少头奶牛可以当明星。

分析题意发现强连通分量中出度为0的点们可能是答案,如果出现两个或以上的出度为0的分量则不存在所有点都能到的点

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 10;
const int maxm = 5e4 + 10;
struct node {
    int to, nxt;
    node() {}
    node(int _to, int _nxt) : to(_to), nxt(_nxt) {}
} E[maxm];
int top, head[maxn];
void addEdge(int u, int v) {
    E[++top] = node(v, head[u]);
    head[u] = top;
}
int dfn[maxn], tot, low[maxn], vis[maxn], clor, clr[maxn], cnt[maxn];
int out[maxn];
stack<int> stk;
void tarjan(int u) {
    dfn[u] = low[u] = ++tot;
    stk.push(u);
    vis[u] = 1;
    for (register int i = head[u]; i; i = E[i].nxt)
    {
        int v = E[i].to;
        if(vis[v] == 0) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(vis[v] == 1)
            low[u] = min(low[u], dfn[v]);
    }
    if(dfn[u] == low[u]) {
        int v;
        clor++;
        do {
            v = stk.top();
            stk.pop();
            vis[v] = -1;
            clr[v] = clor;
            cnt[clor]++;
        } while (v != u);
    }
}
int main()
{
    int n, m, a, b;
    scanf("%d%d", &n, &m);
    register int i;
    for (i = 0; i < m; i++) {
        scanf("%d%d", &a, &b);
        addEdge(a, b);
    }
    for (i = 1; i <= n; i++)
        if(!dfn[i]) tarjan(i);
    for (i = 1; i <= n; i++) {
        for (register int x = head[i]; x; x = E[x].nxt) {
            if(clr[i] == clr[E[x].to]) continue;
            out[clr[i]]++;
        }
    }
    int ans = 0;
    for (i = 1; i <= clor; i++)
    {
        if(!out[i]) {
            if(ans) {
                printf("0\n");
                return 0;
            }
            ans = i;
        }
    }
    printf("%d\n", cnt[ans]);
    // system("pause");
}

猜你喜欢

转载自blog.csdn.net/weixin_40588429/article/details/84107678