题目链接:
题解:
裸Tarjan,每次出栈操作时,记录当前强连通分量中的结点数,与ans1比较,并用ans2记录当前最大强连通分量的序号
1 #include2 #include 3 #include 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 node10 {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 do24 {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 else61 {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 }