tarjan算法+缩点:求强连通分量 POJ 2186
Posted tech-chen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tarjan算法+缩点:求强连通分量 POJ 2186相关的知识,希望对你有一定的参考价值。
强连通分量:1309. [HAOI2006]受欢迎的牛
★★ 输入文件:cow.in
输出文件:cow.out
简单对比
时间限制:1 s 内存限制:128 MB
【题目描述】
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛 A 认为牛
B受欢迎。这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。
【输入格式】
第1行两个整数N,M;
接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)
【输出格式】
一个数,即有多少头牛被所有的牛认为是受欢迎的。
【样例输入】
3 3
1 2
2 1
2 3
【样例输出】
1
【数据范围】
10%的数据N<=20,M<=50
30%的数据N<=1000,M<=20000
70%的数据N<=5000,M<=50000
100%的数据N<=10000,M<=50000
1 /*判断能不能有“牛被所有的牛认为是受欢迎”,那就是缩点之后的图中出度为0的点只有一个,如果图中出度为0的点有多个,肯定不符合情况,找出该点之后,再输出该强连通分量即可*/ 2 #include<iostream> 3 using namespace std; 4 #include<cstdio> 5 #include<cstring> 6 #include<stack> 7 #define N 10010 8 #define M 50010 9 bool in_stack[N]; 10 int low[N],dfn[N],x,y,n,m,father[N]; 11 int chudu[N],t=0,topt=0,head[N]; 12 struct Edge{ 13 int v,last,u; 14 }edge[M*2]; 15 stack<int>sta; 16 int ans[N],begi,en; 17 int read() 18 { 19 int sum=0,ff=1; 20 char s; 21 s=getchar(); 22 while(s<‘0‘||s>‘9‘) 23 { 24 if(s==‘-‘) ff=-1; 25 s=getchar(); 26 } 27 while(s>=‘0‘&&s<=‘9‘) 28 { 29 sum=sum*10+s-‘0‘; 30 s=getchar(); 31 } 32 return sum*ff; 33 } 34 void add_edge(int u,int v,int k) 35 { 36 edge[k].u=u; 37 edge[k].v=v; 38 edge[k].last=head[u]; 39 head[u]=k; 40 } 41 void input() 42 { 43 n=read();m=read(); 44 for(int i=1;i<=m;++i) 45 { 46 x=read();y=read(); 47 add_edge(x,y,i); 48 } 49 } 50 void tarjan(int u) 51 { 52 low[u]=dfn[u]=++topt; 53 sta.push(u); 54 in_stack[u]=true; 55 for(int l=head[u];l;l=edge[l].last) 56 { 57 int v=edge[l].v; 58 if(!dfn[v]) 59 { 60 tarjan(v); 61 low[u]=min(low[u],low[v]); 62 } 63 else if(in_stack[v]) 64 low[u]=min(low[u],dfn[v]); 65 } 66 if(low[u]==dfn[u]) 67 { 68 ans[++ans[0]]=u; 69 int x; 70 do 71 { 72 x=sta.top(); 73 sta.pop(); 74 in_stack[x]=false; 75 father[x]=u; 76 }while(x!=u); 77 } 78 } 79 void suo_dian() 80 { 81 for(int l=1;l<=m;++l) 82 { 83 if(father[edge[l].v]!=father[edge[l].u]) 84 { 85 chudu[father[edge[l].u]]++; 86 } 87 } 88 } 89 int main() 90 { 91 freopen("cow.in","r",stdin); 92 freopen("cow.out","w",stdout); 93 input(); 94 for(int i=1;i<=n;++i) 95 { 96 if(!dfn[i]) 97 { 98 tarjan(i); 99 } 100 } 101 suo_dian(); 102 int sum=0,l; 103 for(int i=1;i<=ans[0];++i) 104 if(chudu[ans[i]]==0) 105 { 106 sum++; 107 l=ans[i]; 108 } 109 if(sum>1) printf("0"); 110 else if(sum==1) 111 { 112 sum=0; 113 for(int i=1;i<=n;++i) 114 if(father[i]==l) 115 sum++; 116 printf("%d\n",sum); 117 } 118 fclose(stdin);fclose(stdout); 119 return 0; 120 }
以上是关于tarjan算法+缩点:求强连通分量 POJ 2186的主要内容,如果未能解决你的问题,请参考以下文章
POJ-3180 The Cow Prom(tarjan求强连通分量)