[HAOI2006]受欢迎的牛(tarjan缩点)

洛谷传送门

直接tarjan求scc,然后统计出度为0的缩点,如果多余1个就输出0,只有一个就输出这个缩点里的点。

——代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <stack>
 4 
 5 using namespace std;
 6 
 7 int n, m, cnt, idx, ans, k;
 8 int next[100001], to[100001], head[10001], low[10001], dfn[10001], belong[10001], c[10001];
 9 bool ins[10001];
10 stack <int> s;
11 
12 inline void add(int x, int y)
13 {
14     to[cnt] = y;
15     next[cnt] = head[x];
16     head[x] = cnt++;
17 }
18 
19 inline void tarjan(int u)
20 {
21     low[u] = dfn[u] = ++idx;
22     s.push(u);
23     ins[u] = 1;
24     int i, v;
25     for(i = head[u]; i != -1; i = next[i])
26     {
27         v = to[i];
28         if(!dfn[v])
29         {
30             tarjan(v);
31             low[u] = min(low[u], low[v]);
32         }
33         else if(ins[v]) low[u] = min(low[u], dfn[v]);
34     }
35     if(low[u] == dfn[u])
36     {
37         cnt++;
38         do
39         {
40             v = s.top();
41             s.pop();
42             ins[v] = 0;
43             belong[v] = cnt;
44         }while(u != v);
45     }
46 }
47 
48 int main()
49 {
50     int i, j, x, y, u, v;
51     memset(head, -1, sizeof(head));
52     scanf("%d %d", &n, &m);
53     for(i = 1; i <= m; i++)
54     {
55         scanf("%d %d", &x, &y);
56         add(x, y);
57     }
58     cnt = 0;
59     for(i = 1; i <= n; i++)
60      if(!dfn[i])
61       tarjan(i);
62     for(u = 1; u <= n; u++)
63      for(i = head[u]; i != -1; i = next[i])
64      {
65          v = to[i];
66          if(belong[u] != belong[v]) c[belong[u]]++;
67      }
68     for(i = 1; i <= cnt; i++)
69      if(!c[i])
70      {
71          ans++;
72          k = i;
73      }
74     if(ans > 1)    printf("0");
75     else
76     {
77         ans = 0;
78         for(i = 1; i <= n; i++)
79          if(belong[i] == k)
80           ans++;
81         printf("%d", ans);
82     }
83     return 0;
84 }
View Code
原文地址:https://www.cnblogs.com/zhenghaotian/p/6707063.html