D19 vDCC 缩点 Tarjan 算法
D19 vDCC 缩点 Tarjan 算法_哔哩哔哩_bilibili

vDCC:不删除边,分裂割点,构成的连通块
把 vDCC 缩成点,把缩点和割点对应连边,构成树
1. cut[x] 记录割点,dcc[] 记录 vDCC,id[] 割点的编号
2. 每次回溯:判割点,记录 vDCC
3. 特判孤立点,忽略自环
#include<bits/stdc++.h> using namespace std; const int N=10010; int n,m,a,b; vector<int> e[N],ne[N],dcc[N]; int dfn[N],low[N],tot,stk[N],top,cut[N],root,cnt; int id[N]; void tarjan(int x){ dfn[x]=low[x]=++tot; stk[++top]=x; if(x==root&&!e[x].size()){ //孤立点 dcc[++cnt].push_back(x); return; } int son=0; for(int y:e[x]){ if(!dfn[y]){ //若y未访问 tarjan(y); low[x]=min(low[x],low[y]); if(low[y]>=dfn[x]){ son++; if(x!=root||son>1)cut[x]=1; //割点 ++cnt; while(1){ int z=stk[top--]; dcc[cnt].push_back(z); if(z==y) break; //让x留在栈中 } dcc[cnt].push_back(x); //vDCC } } else //若y已访问 low[x]=min(low[x],dfn[y]); } } int main(){ cin>>n>>m; while(m--){ cin>>a>>b; e[a].push_back(b), e[b].push_back(a); } for(root=1;root<=n;root++)if(!dfn[root])tarjan(root); //给每个割点一个新编号(cnt+1开始) int num=cnt; for(int i=1;i<=n;i++)if(cut[i])id[i]=++num; //建树,从每个缩点向对应割点连边 for(int i=1;i<=cnt;i++){ for(int j=0;j<dcc[i].size();j++){ int x=dcc[i][j]; if(cut[x]){ ne[i].push_back(id[x]), ne[id[x]].push_back(i); } } } }
#include<bits/stdc++.h> using namespace std; const int N=500010; int n,m,a,b; vector<int> e[N],ne[N],dcc[N]; int dfn[N],low[N],tot,stk[N],top,cut[N],root,cnt; void tarjan(int x){ if(x==root&&!e[x].size()){ //孤立点 dcc[++cnt].push_back(x); return; } dfn[x]=low[x]=++tot; stk[++top]=x; int son=0; for(int y:e[x]){ if(!dfn[y]){ //若y未访问 tarjan(y); low[x]=min(low[x],low[y]); if(low[y]>=dfn[x]){ son++; if(x!=root||son>1)cut[x]=1; //割点 ++cnt; while(1){ int z=stk[top--]; dcc[cnt].push_back(z); if(z==y) break; //让x留在栈中 } dcc[cnt].push_back(x); //vDCC } } else //若y已访问 low[x]=min(low[x],dfn[y]); } } int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin>>n>>m; while(m--){ cin>>a>>b; if(a==b) continue; //忽略自环 e[a].push_back(b), e[b].push_back(a); } for(root=1;root<=n;root++)if(!dfn[root])tarjan(root); cout<<cnt<<"\n"; for(int i=1;i<=cnt;i++){ cout<<dcc[i].size()<<" "; for(int j:dcc[i])cout<<j<<" "; cout<<"\n"; } }
浙公网安备 33010602011771号