简单tarjan》一道裸题(BZOJ1051)(easy)
这是一道水题,实际考察的是你会不会写强连通分量。。。(在BZOJ上又水了一道题)
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
1 2
2 1
2 3
Sample Output
1
HINT
100%的数据N<=10000,M<=50000
思路:直接强连通分量缩点,然后,因为题目没有告诉你 当没有一头牛受欢迎时 应该输出什么,所以我们认为题目一定有解,所以直接tarjan就好啦
强行给出代码
1 #include<stdio.h> 2 #include<string.h> 3 int head[11000],F[11000],w[11000],ass,stack[11000],n,point,m,D[11000],ans; 4 int min(int x,int y) 5 { 6 return x>y?y:x; 7 } 8 bool f[11000]; 9 struct shit{ 10 int aim,next,from; 11 }e[51000]; 12 int T,time[51000],dfn[51000]; 13 void tarjan(int x) 14 { 15 time[x]=dfn[x]=++T; 16 f[x]=true; 17 stack[++ass]=x; 18 for(int k=head[x];k;k=e[k].next) 19 { 20 int v=e[k].aim; 21 if(!time[v]) 22 { 23 tarjan(v); 24 dfn[x]=min(dfn[x],dfn[v]); 25 } 26 else if(f[e[k].aim])dfn[x]=min(dfn[x],time[v]); 27 } 28 if(dfn[x]==time[x]) 29 { 30 f[x]=false; 31 while(stack[ass]!=x) 32 { 33 w[x]++; 34 F[stack[ass]]=x; 35 f[stack[ass--]]=false; 36 } 37 ass--; 38 } 39 } 40 void fuck(int x,int y) 41 { 42 e[++point].aim=y; 43 e[point].from=x; 44 e[point].next=head[x]; 45 head[x]=point; 46 } 47 int main() 48 { 49 int a,b; 50 scanf("%d%d",&n,&m); 51 for(int i=1;i<=m;++i) 52 { 53 scanf("%d%d",&a,&b); 54 fuck(a,b); 55 } 56 for(int i=1;i<=n;++i)F[i]=i,w[i]=1; 57 for(int i=1;i<=n;++i) 58 if(!time[i])tarjan(i); 59 memset(head,0,sizeof(head)); 60 point=0; 61 for(int i=1;i<=m;++i) 62 { 63 if(F[e[i].from]==F[e[i].aim])continue; 64 else { 65 D[F[e[i].from]]++; 66 fuck(F[e[i].aim],F[e[i].from]); 67 } 68 } 69 for(int i=1;i<=n;i++) 70 if(F[i]==i&&!D[i])ans+=w[i]; 71 printf("%d",ans); 72 return 0; 73 }
没什么好PS的