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
",ans1);
70     for(int i=1;i<=n;i++)
71     {
72         if(belong[i]==ans2)printf("%d ",i);//如果该结点属于最大强连通分量,输出 
73     }
74     return 0;
75 }
原文地址:https://www.cnblogs.com/xqmmcqs/p/5965769.html