bzoj 1051 受欢迎的牛

题目大意:

现在有N头牛,给一个 A B 表示牛A认为牛B受欢迎

这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少牛被所有的牛认为是受欢迎的

思路:

先用tarjan把每个强连通分量缩点

然后脑补一下

可以发现如果有大于一个连通分量出度为零,则不可能有解  因为这几个出度为零部分的牛互相不能认为对方受欢迎

所以只有当所有强连通分量只有一个出度为零的时候 解为那个连通分量的大小

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<set>
 8 #include<map>
 9 #include<vector>
10 #include<stack>
11 #include<queue>
12 #define ll long long
13 #define inf 2147383611
14 #define MAXN 100100
15 #define MOD 5050
16 using namespace std;
17 inline int read()
18 {
19     int x=0,f=1;
20     char ch;ch=getchar();
21     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
22     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
23     return x*f;
24 }
25 int n,m,next[MAXN*2],first[MAXN],to[MAXN*2],cnt;
26 int Next[MAXN*2],First[MAXN],To[MAXN*2],otd[MAXN];
27 int scc,dfn[MAXN],low[MAXN],bl[MAXN],stp,num[MAXN];
28 bool vis[MAXN];
29 int st[MAXN],top;
30 void add(int u,int v) {next[++cnt]=first[u],first[u]=cnt,to[cnt]=v;}
31 void ADD(int u,int v) {Next[++cnt]=First[u],First[u]=cnt,To[cnt]=v;otd[u]++;}
32 void tarjan(int x)
33 {
34     low[x]=dfn[x]=++stp,st[++top]=x,vis[x]=1;
35     for(int i=first[x];i;i=next[i])
36     {
37         if(!dfn[to[i]])
38         {
39             tarjan(to[i]);low[x]=min(low[x],low[to[i]]);
40         }
41         else if(vis[to[i]]) low[x]=min(low[x],dfn[to[i]]);
42     }
43     if(low[x]==dfn[x])
44     {
45         scc++;
46         while(st[top+1]!=x) bl[st[top]]=scc,num[scc]++,vis[st[top]]=0,top--;
47     }
48 }
49 void rebuild()
50 {
51     cnt=0;
52     for(int i=1;i<=n;i++)
53         for(int j=first[i];j;j=next[j])
54             if(bl[i]!=bl[to[j]]) ADD(bl[i],bl[to[i]]);
55 }
56 int main()
57 {
58     n=read(),m=read();
59     int a,b;
60     while(m--)
61     {
62         a=read(),b=read();
63         add(a,b);
64     }
65     for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
66     rebuild();
67     cnt=0;int k;
68     for(int i=1;i<=scc;i++) if(!otd[i]) {cnt++;k=i;}
69     if(cnt==1) printf("%d",num[k]);
70     else printf("0");
71 }
View Code

 

posted @ 2017-10-30 19:16  jack_yyc  阅读(...)  评论(... 编辑 收藏