[BZOJ1051][HAOI2006] 受欢迎的牛 tarjan求联通分量

1051: [HAOI2006]受欢迎的牛

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 5687  Solved: 3016
[Submit][Status][Discuss]

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求强联通分量并缩点,对于缩点后的每一个点,若他是唯一出度为0的点,就说明他之中的所有牛被众人%膜拜%,否则无解。
代码:
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<cstdlib>
 7 using namespace std;
 8 struct data
 9 {
10     int next,to;
11 }e[100001],e1[100001];
12 int n,m;
13 int head[50005],cnt,head1[50005],cnt1;
14 int dfn[50005],low[50005];
15 bool vis[50005],inq[50005];
16 int q[50005],top;
17 int tim;
18 int scc;
19 int size[50005];
20 int belong[50005];
21 void add(int u,int v){e[cnt].next=head[u];e[cnt].to=v;head[u]=cnt;cnt++;}
22 void add1(int u,int v){e1[cnt1].next=head1[u];e1[cnt1].to=v;head1[u]=cnt1;cnt1++;}
23 void dfs(int now)
24 {
25     dfn[now]=low[now]=++tim;
26     vis[now]=inq[now]=1;
27     q[++top]=now;
28     for(int i=head[now];i>=0;i=e[i].next)
29     {
30         int to=e[i].to;
31         if(!vis[to])
32         {
33             dfs(to);
34             low[now]=min(low[to],low[now]);
35         }
36         else if(inq[to]) low[now]=min(low[now],dfn[to]);
37     }
38     if(low[now]==dfn[now])
39     {
40         scc++;
41         int c=0;
42         while(c!=now)
43         {
44             c=q[top--];
45             inq[c]=0;
46             belong[c]=scc;
47             size[scc]++;
48         }
49     }
50 }
51 void rebuild()
52 {
53     memset(head1,-1,sizeof(head1));
54     for(int i=1;i<=n;i++)
55         for(int j=head[i];j>=0;j=e[j].next)
56         {
57             int to=e[j].to;
58             if(belong[i]!=belong[to]) add1(belong[i],belong[to]);
59         }
60 }
61 void tarjan()
62 {
63     for(int i=1;i<=n;i++) if(!vis[i]) dfs(i);
64     rebuild();
65 }
66 void work()
67 {
68     int ans=0;
69     for(int i=1;i<=scc;i++)
70     {
71         if(head1[i]==-1)
72         {
73             if(ans){ans=0;cout<<ans;return ;}
74             else{ans=size[i];}
75         }
76     }
77     cout<<ans;
78 }
79 int main()
80 {
81     memset(head,-1,sizeof(head));
82     scanf("%d%d",&n,&m);
83     for(int i=1;i<=m;i++)
84     {
85         int u,v;
86         scanf("%d%d",&u,&v);
87         add(u,v);
88     }
89     tarjan();
90     work();
91 }
92 
View Code

 

posted @ 2017-07-20 09:56  wls001  阅读(171)  评论(0编辑  收藏  举报