1051. [HAOI2006]受欢迎的牛【强连通分量】

Description

  每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
牛被所有的牛认为是受欢迎的。

Input

  第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可
能出现多个A,B)

Output

  一个数,即有多少头牛被所有的牛认为是受欢迎的。

Sample Input

3 3
1 2
2 1
2 3

Sample Output

1

HINT

100%的数据N<=10000,M<=50000

求有多少个点,使得所有其他点都有一条到它的路径。
嘛……很好的一个tarjan模板题……问题是垃圾LXXGU的数据太恶心
竟然有多个图的数据(强行给自己的菜开脱)
这个题就是将图缩点缩成一个有向无环图
若只有一个点出度为0那么这个点必然被所有牛喜欢
反证:要是有多个点出度为0,那么这些出度为0的点必然不会喜欢其他出度为0的点

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #define MAXN (100000+5)
 6 #define MAXM (100000+5)
 7 using namespace std;
 8 int Dfn[MAXN],Low[MAXN],Outd[MAXN];
 9 int Dfs_num,Col_num,Color[MAXN],Cnt[MAXN];
10 int u[MAXM],v[MAXM];
11 int stack[MAXN],top;
12 bool Vis[MAXN];
13 int head[MAXN],num_edge;
14 struct node
15 {
16     int next;
17     int to;
18 } edge[MAXM*2];
19 
20 void add(int u,int v)
21 {
22     edge[++num_edge].to=v;
23     edge[num_edge].next=head[u];
24     head[u]=num_edge;
25 }
26 
27 void Tarjan(int x)
28 {
29     Dfn[x]=++Dfs_num;
30     Low[x]=Dfs_num;
31     Vis[x]=true;
32     stack[++top]=x;
33     for (int i=head[x]; i!=0; i=edge[i].next)
34         if (!Dfn[edge[i].to])
35         {
36             Tarjan(edge[i].to);
37             Low[x]=min(Low[x],Low[edge[i].to]);
38         }
39         else if (Vis[edge[i].to])
40             Low[x]=min(Low[x],Dfn[edge[i].to]);
41     if (Dfn[x]==Low[x])
42     {
43         Vis[x]=false;
44         Color[x]=++Col_num;
45         Cnt[Col_num]++;
46         while (stack[top]!=x)
47         {
48             Cnt[Col_num]++;
49             Color[stack[top]]=Col_num;
50             Vis[stack[top--]]=false;
51         }
52         --top;
53     }
54 }
55 int main()
56 {
57     int n,m;
58     scanf("%d%d",&n,&m);
59     for (int i=1; i<=m; ++i)
60     {
61         scanf("%d%d",&u[i],&v[i]);
62         add(u[i],v[i]);
63     }
64     for (int i=1; i<=n; ++i)
65         if (!Dfn[i])
66             Tarjan(i);
67     for (int i=1; i<=m; ++i)
68         if (Color[u[i]]!=Color[v[i]])
69             ++Outd[Color[u[i]]];
70 
71     int Ans=0;
72     for (int i=1; i<=Col_num; ++i)
73         if (Outd[i]==0)
74             if (Ans==0)
75                 Ans=Cnt[i];
76             else
77             {
78                 printf("0");
79                 return 0;
80             }
81     printf("%d",Ans);
82 }
原文地址:https://www.cnblogs.com/refun/p/8678485.html