无向图边双+缩点
#include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<stack> using namespace std; struct my{ int next; int v; }; const int maxn=10000; int adj[maxn],low[maxn],dfsn[maxn],dfn,fa,id[maxn],sadj[maxn],sfa; my bian[maxn*2],sbian[maxn*2]; bool cut[maxn]; int sccnum; int s[maxn],top,root; vector<int>scc[maxn]; void myinsert(int u,int v){ bian[++fa].v=v; bian[fa].next=adj[u]; adj[u]=fa; } void smyinsert(int u,int v){ sbian[++sfa].v=v; sbian[sfa].next=sadj[u]; sadj[u]=sfa; } void tarjan(int x){ s[++top]=x; low[x]=dfsn[x]=++dfn; int ch=0; if(x==root&&!adj[x]){ scc[++sccnum].push_back(x); return ; } for (int i=adj[x];i;i=bian[i].next){ int v=bian[i].v; if(!dfsn[v]){ tarjan(v); low[x]=min(low[x],low[v]); if(dfsn[x]<=low[v]){ ch++; sccnum++; int z; do{ z=s[top--]; scc[sccnum].push_back(z); }while(z!=v); scc[sccnum].push_back(x); if(x!=root||ch>1) cut[x]=true; } }else low[x]=min(low[x],dfsn[v]); } } int main(){ int n,m; int u,v; scanf("%d%d",&n,&m); for (int i=1;i<=m;i++){ scanf("%d%d",&u,&v); myinsert(u,v); myinsert(v,u); } for (int i=1;i<=n;i++){ if(!dfsn[i]) { root=i; tarjan(i); } } int num=sccnum; for (int i=1;i<=n;i++) if(cut[i]) id[i]=++num; for (int i=1;i<=sccnum;i++){ for (int j=0;j<scc[i].size();j++){ int x=scc[i][j]; if(cut[x]){ smyinsert(i,id[x]); smyinsert(id[x],i); } } } for (int i=1;i<=num;i++){ printf("%d ",i); for (int j=sadj[i];j;j=sbian[j].next){ int v=sbian[j].v; printf("%d ",v); } printf("\n"); } return 0; }