BZOJ-1051: [HAOI2006]受欢迎的牛(tarjan求强连通分量)

1051: [HAOI2006]受欢迎的牛

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 4194  Solved: 2247
[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

 

Source

 

只要找到缩点后的图中无出度的点的个数,设为count, 若 count > 1 , 则必无满足条件的点,因为一个出度为零的点无法到达另一个出度为零的点;若count = 1 , 则该点所对应的强联通分量的点的个数即为答案。

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <iostream>
 6 #include "algorithm"
 7 using namespace std;
 8 typedef long long LL;
 9 const int MAX1=10005;
10 const int MAX2=50005;
11 int n,m;
12 int tot,c;
13 int dfn[MAX1],low[MAX1],ins[MAX1];
14 int head[MAX1],adj[MAX2],next[MAX2];
15 bool t[MAX1];
16 int sta[MAX1],gid[MAX1],con[MAX1];
17 int out,tx;
18 int ans;
19 void addedge(int u,int v){
20     tot++;
21     adj[tot]=v;
22     next[tot]=head[u];
23     head[u]=tot;
24 }
25 void init(){
26     int i,j;
27     int u,v;
28     scanf("%d%d",&n,&m);
29     memset(gid,0,sizeof(gid));
30     memset(next,0,sizeof(next));
31     memset(ins,0,sizeof(ins));
32     for (i=1;i<=m;i++)
33     {scanf("%d%d",&u,&v);
34      addedge(u,v);
35     }
36     memset(t,false,sizeof(t));
37     tx=out=ans=c=sta[0]=0;
38 }
39 int dfs(int x){
40     int i,j;
41     t[x]=true;
42     sta[++sta[0]]=x;ins[x]=1;
43     dfn[x]=++c;low[x]=dfn[x];
44     for (i=head[x];i;i=next[i])
45      if (t[adj[i]])
46      {if (ins[adj[i]]==1)
47        low[x]=min(low[x],dfn[adj[i]]);}
48      else
49      {j=dfs(adj[i]);
50       low[x]=min(low[x],j);
51      }
52     if (low[x]>=dfn[x])
53     {con[0]=0;
54      tx++;out++;
55      while (1)
56      {con[++con[0]]=sta[sta[0]];
57       gid[sta[sta[0]]]=tx;
58       ins[sta[sta[0]]]=0;
59       if (sta[sta[0]]==x)
60       {sta[0]--;
61        break;
62       }
63       sta[0]--;
64      }
65      bool ls;
66      ls=true;
67      for (i=1;i<=con[0];i++)
68       for (j=head[con[i]];j;j=next[j])
69        if (gid[con[i]]!=gid[adj[j]])
70         ls=false;
71      if (!ls) out--;   
72      else ans=con[0];
73     }
74     else return low[x];
75 }
76 int main(){
77     init();int i,j;
78     for (i=1;i<=n;i++)
79      if (!t[i])
80       j=dfs(i);
81     if (out>1)
82      printf("0");
83     else
84      printf("%d",ans);
85     return 0;
86 }

 

posted @ 2016-08-01 10:35  lonely_OIer  阅读(235)  评论(0编辑  收藏  举报