WHYZOJ-#64 上白泽慧音(tarjan求强连通分量)
Posted 可惜没如果=_=
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WHYZOJ-#64 上白泽慧音(tarjan求强连通分量)相关的知识,希望对你有一定的参考价值。
【题目描述】:
在幻想乡,上白泽慧音是以知识渊博闻名的老师。春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄。因此慧音决定换一个能够聚集最多人数的村庄作为新的教学地点。
人间之里由N个村庄(编号为1..N)和M条道路组成,道路分为两种一种为单向通行的,一种为双向通行的,分别用1和2来标记。
如果存在由村庄A到达村庄B的通路,那么我们认为可以从村庄A到达村庄B,记为(A,B)。当(A,B)和(B,A)同时满足时,我们认为A,B是绝对连通的,记为。绝对连通区域是指一个村庄的集合,在这个集合中任意两个村庄X,Y都满足。
现在你的任务是,找出最大的绝对连通区域,并将这个绝对连通区域的村庄按编号依次输出。若存在两个最大的,输出字典序最小的,比如当存在1,3,4和2,5,6这两个最大连通区域时,输出的是1,3,4。
【输入描述】:
第1行:两个正整数N,M
第2..M+1行:每行三个正整数a,b,t, t = 1表示存在从村庄a到b的单向道路,t = 2表示村庄a,b之间存在双向通行的道路。保证每条道路只出现一次。
【输出描述】:
第1行: 1个整数,表示最大的绝对连通区域包含的村庄个数。
第2行:若干个整数,依次输出最大的绝对连通区域所包含的村庄编号。
【样例输入】:
5 5
1 2 1
1 3 2
2 4 2
5 1 2
3 5 1
【样例输出】:
3
1 3 5
【时间限制、数据范围及描述】:
时间:1s 空间:128M
对于60%的数据:N <= 200且M <= 10,000
对于100%的数据:N <= 5,000且M <= 50,000
肫帮我发现了我写的tarjan一直存在的bug(最开始的好像没有,后来由于POJ的辣鸡数据,好好的板子就被我打歪了还不自知),第一个判断下一个节点是否访问的时候同时要判断是否在栈中
1 #include <cstdio> 2 #include <cmath> 3 #include <cstring> 4 #include <cstdlib> 5 #include <queue> 6 #include <stack> 7 #include <vector> 8 #include <iostream> 9 #include "algorithm" 10 #define mem(a,b) memset(a,b,sizeof(a)) 11 using namespace std; 12 typedef long long LL; 13 const int MAX1=5005; 14 const int MAX2=100005; 15 int n,m; 16 int head[MAX1],adj[MAX2],next[MAX2]; 17 int tot,tx; 18 int low[MAX1],dfn[MAX1],sta[MAX1]; 19 bool t[MAX1],tt[MAX1]; 20 int ans[MAX1]; 21 inline int read(){ 22 int x=1,an=0;char c=getchar(); 23 while (c<‘0‘ || c>‘9‘){if (c==‘-‘) x=-1;c=getchar();} 24 while (c>=‘0‘ && c<=‘9‘){an=an*10+c-‘0‘;c=getchar();} 25 return x*an; 26 } 27 void addedge(int u,int v){ 28 tot++; 29 adj[tot]=v; 30 next[tot]=head[u]; 31 head[u]=tot; 32 } 33 void init(){ 34 int i,j; 35 n=read();m=read(); 36 int x,y,z; 37 ans[0]=sta[0]=tot=tx=0; 38 mem(head,0),mem(t,false),mem(tt,false); 39 for (i=1;i<=m;i++){ 40 x=read();y=read();z=read(); 41 if (z==1) addedge(x,y); 42 if (z==2) addedge(x,y),addedge(y,x); 43 } 44 } 45 void tarjan(int x){ 46 sta[++sta[0]]=x; 47 dfn[x]=low[x]=++tx; 48 tt[x]=t[x]=true; 49 int i,j; 50 for (i=head[x];i;i=next[i]){ 51 if (t[adj[i]] && tt[adj[i]]) 52 low[x]=min(low[x],dfn[adj[i]]); 53 else{ 54 tarjan(adj[i]); 55 low[x]=min(low[x],low[adj[i]]); 56 } 57 } 58 if (low[x]>=dfn[x]){ 59 int zt[MAX1]; 60 zt[0]=0; 61 do{ 62 tt[sta[sta[0]]]=false; 63 zt[++zt[0]]=sta[sta[0]]; 64 }while (sta[sta[0]--]!=x); 65 if (zt[0]>ans[0]) 66 for (i=0;i<=zt[0];i++) ans[i]=zt[i]; 67 if (zt[0]==ans[0]){ 68 bool flag=true; 69 sort(zt+1,zt+zt[0]+1); 70 for (i=1;i<=zt[0];i++){ 71 if (zt[i]>ans[i]){ 72 flag=false; 73 break; 74 } 75 } 76 if (flag) 77 for (i=0;i<=zt[0];i++) ans[i]=zt[i]; 78 } 79 } 80 } 81 int main(){ 82 freopen ("classroom.in","r",stdin); 83 freopen ("classroom.out","w",stdout); 84 init();int i,j; 85 for (i=1;i<=n;i++){ 86 if (!t[i]) 87 tarjan(i); 88 } 89 sort(ans+1,ans+ans[0]+1); 90 printf("%d\n",ans[0]); 91 for (i=1;i<=ans[0];i++) 92 printf("%d ",ans[i]); 93 return 0; 94 }
以上是关于WHYZOJ-#64 上白泽慧音(tarjan求强连通分量)的主要内容,如果未能解决你的问题,请参考以下文章