图联通模板全集
强连通模板
void tarjan(int x) {
dfn[x]=low[x]=++tot;
stk[++top]=x;
vis[x]=1;
for(int i=head[x]; i; i=G[i].nxt) {
int y=G[i].to;
if(!dfn[y]) {
tarjan(y);
low[x]=min(low[x],low[y]);
} else if(vis[y]) {
low[x]=min(low[x],dfn[y]);
}
}
if(low[x]==dfn[x]) {
int y;
cnt++;
do {
y=stk[top--];
vis[y]=0;
col[y]=cnt;
} while(y!=x);
}
}
点双模板
求点双分量的点(方便造点方树,可以有重边)
void tarjan(int x) {
dfn[x]=low[x]=++tot;
stk[++Top]=x;
int cnt=0;
for(int i=head[x]; i; i=G[i].nxt) {
int y=G[i].to;
if(!dfn[y]) {
cnt++;
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]) {
mark[x]=1;
BL[++blk].push_back(x);
do {
BL[blk].push_back(stk[Top--]);
} while(y!=stk[Top+1]);
}
} else {
low[x]=min(low[x],dfn[y]);
}
}
if(x==root&&cnt==1)mark[x]=0;
}
求点双的边和点(这份模板不能判重边)
void tarjan(int x,int f) {
dfn[x]=low[x]=++tot;
for(int i=head[x]; i; i=G[i].nxt) {
int y=G[i].to;
if(!dfn[y]) {
stk[++Top].rd(x,y);
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]) {
blk++;
int a,b;
do {
a=stk[Top].a;
b=stk[Top].b;
if(col[a]!=blk)col[a]=blk,BL[blk].push_back(a);
if(col[b]!=blk)col[b]=blk,BL[blk].push_back(b);
ADD(a,b);
Top--;
} while(a!=x&&b!=y);
}
} else if(y!=f&&dfn[y]<dfn[x]) {
stk[++Top].rd(x,y);
low[x]=min(low[x],dfn[y]);
}
}
}
边双模板
求桥(可以有重边)
void tarjan(int x,int fa) {
dfn[x]=low[x]=++tot;
for(int i=head[x]; i; i=G[i].nxt) {
int y=G[i].to;
if(!dfn[y]) {
tarjan(y,G[i].id);
low[x]=min(low[x],low[y]);
if(low[y]>dfn[x]) {
mark[G[i].id]=1;
}
} else if(G[i].id!=fa) {
low[x]=min(low[x],dfn[y]);
}
}
}