1 #include<cstdio>
 2 #include<iostream>
 3 #define M 50008
 4 using namespace std;
 5 int du[M],ti,ti1,cnt,head[M],head1[M],next1[10*M],u1[10*M],next[10*M],u[M],n,m,dfn[M],low[M],t,zhan[M],f[M],bel[M],sum[M];
 6 void jia(int a1,int a2)
 7 {
 8     cnt++;
 9     next[cnt]=head[a1];
10     head[a1]=cnt;
11     u[cnt]=a2;
12 }
13 void jia1(int a1,int a2)
14 {
15     cnt++;
16     next1[cnt]=head1[a1];
17     head1[a1]=cnt;
18     u1[cnt]=a2; 
19     du[a1]++;
20 }
21 void tarjin(int a1)
22 {
23     dfn[a1]=low[a1]=++ti;
24     f[a1]=1;
25     t++;
26     zhan[t]=a1;
27     for(int i=head[a1];i;i=next[i])
28       if(!dfn[u[i]])
29         {
30             tarjin(u[i]);
31             low[a1]=min(low[a1],low[u[i]]);
32         }
33       else  if(f[u[i]])
34                low[a1]=min(low[a1],dfn[u[i]]);
35     if(dfn[a1]==low[a1])
36       {
37         ++ti1;
38         int now=0;
39         for(;now!=a1;)
40           {
41             now=zhan[t];
42             bel[now]=ti1;
43             sum[ti1]++;
44             f[now]=0;
45             t--;
46           }
47       }
48 }
49 void jian()
50 {
51     cnt=0;
52     for(int i=1;i<=n;i++)
53       for(int j=head[i];j;j=next[j])
54         if(bel[i]!=bel[u[j]])
55            jia1(bel[i],bel[u[j]]);
56 }
57 int main()
58 {
59     scanf("%d%d",&n,&m);
60     for(int i=1;i<=m;i++)
61       {
62         int a1,a2;
63         scanf("%d%d",&a1,&a2);
64         jia(a1,a2);
65       }
66     for(int i=1;i<=n;i++)
67       if(!dfn[i])
68         tarjin(i);
69     jian();
70     int s=0,s1;
71     for(int i=1;i<=ti1;i++)
72       if(!du[i])
73         {
74             s++;
75             s1=i;
76         }
77     if(s>1)
78       printf("0");
79     else
80       printf("%d",sum[s1]);
81     return 0;
82 }

按题目建图后,用tarjan缩点,统计没有出度的联通块的个数,如果只有一个,输出这个联通块内点的个数,否则为零。

posted on 2016-03-01 22:34  xiyuedong  阅读(...)  评论(... 编辑 收藏