codevs 1332 上白泽慧音
题目链接:http://codevs.cn/problem/1332/
题解:
裸Tarjan,每次出栈操作时,记录当前强连通分量中的结点数,与ans1比较,并用ans2记录当前最大强连通分量的序号
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define MAXN 5010 6 #define MAXM 50010 7 int n,m,time,cnt,heads[MAXN],DFN[MAXN],Low[MAXN],stack[MAXN],top,ans1,ans2,belong[MAXN]; 8 bool vis[MAXN]; 9 struct node 10 { 11 int v,next; 12 }edge[MAXM]; 13 void add(int x,int y) 14 { 15 edge[++cnt].next=heads[x]; 16 heads[x]=cnt; 17 edge[cnt].v=y; 18 } 19 void _(int x)//出栈 20 { 21 int i,j=0; 22 cnt++;//强连通分量序号更新 23 do 24 { 25 i=stack[top--]; 26 vis[i]=false; 27 belong[i]=cnt; 28 j++; 29 }while(x!=i); 30 if(j>=ans1)//更新最大强连通分量结点数和序号 31 { 32 ans1=j; 33 ans2=cnt; 34 } 35 } 36 void tarjan(int x) 37 { 38 DFN[x]=Low[x]=++time; 39 vis[x]=true; 40 stack[++top]=x; 41 for(int i=heads[x];i!=0;i=edge[i].next) 42 { 43 if(!DFN[edge[i].v]) 44 { 45 tarjan(edge[i].v); 46 Low[x]=min(Low[x],Low[edge[i].v]); 47 } 48 else if(vis[edge[i].v])Low[x]=min(Low[x],DFN[edge[i].v]); 49 } 50 if(DFN[x]==Low[x])_(x); 51 } 52 int main() 53 { 54 scanf("%d%d",&n,&m); 55 for(int i=1;i<=m;i++) 56 { 57 int x,y,z; 58 scanf("%d%d%d",&x,&y,&z); 59 if(z==1)add(x,y); 60 else 61 { 62 add(x,y); 63 add(y,x); 64 } 65 } 66 cnt=0; 67 for(int i=1;i<=n;i++) 68 if(!DFN[i])tarjan(i); 69 printf("%d\n",ans1); 70 for(int i=1;i<=n;i++) 71 { 72 if(belong[i]==ans2)printf("%d ",i);//如果该结点属于最大强连通分量,输出 73 } 74 return 0; 75 }