#include<bits/stdc++.h>
using namespace std;
const int N=2e6;
typedef long long ll;
struct Node
{
int v,next;
ll w;
}edge[2*N];
//adge为初始的旧点的连接关系,edge为新节点的连接关系
int head[N],cnt;
void add_edge(int u,int v,ll w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
bool vis[N];
//sign[i]表示i节点属于第几个最大强连通图
int DFN[N],LOW[N],sign[N];
stack<int>stk;
int ind,sign_ans,n,m;
void TarJan(int u)
{
++ind;
DFN[u]=LOW[u]=ind;
stk.push(u);
vis[u]=true;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(!DFN[v])
{
TarJan(v);
LOW[u]=min(LOW[u],LOW[v]);
}
else if(vis[v])
LOW[u]=min(LOW[u],DFN[v]);
}
if(DFN[u]==LOW[u])
{
sign_ans++;
int s;
cout<<"第"<<sign_ans<<"个最大强连通图: ";
do{
s=stk.top();
stk.pop();
//标记旧点属于哪个新点集合
sign[s]=sign_ans;
vis[s]=false;
//打印路径
cout<<s<<" ";
}
while(u!=s);
cout<<endl;
}
}
int main()
{
scanf("%d%d",&n,&m);
cnt=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++)
{
int u,v;
//针对带权图
ll w;
scanf("%d%d",&u,&v);
if(u==v)continue;
add_edge(u,v,0);
}
sign_ans=0;
for(int i=1;i<=n;i++)
{
if(!DFN[i])
TarJan(i);
}
return 0;
}
/*
5 5
1 2
2 3
3 1
3 4
4 5
*/
图论最大强连通分量+输出路径模板
最新推荐文章于 2023-01-25 14:51:48 发布