tarjan全家桶
tarjan
1.点强连通分量
单向边
int n,m;
int co[N],col;
int dfn[N],low[N],tim;
int top,st[N];
void tarjan(int x)
{
dfn[x]=low[x]=++tim;
st[++top]=x;
for(int i=h[x],v;i;i=e[i].nt)
{
if(!dfn[v=e[i].to])
{
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if(!co[v])low[x]=min(low[x],dfn[v]);
}
if(dfn[x]==low[x])
{
co[x]=++col;
while(st[top]!=x)co[st[top--]]=col;
top--;
}
}
signed main()
{
n=read();m=read();
for(int i=1;i<=m;i++)
{
int x=read(),y=read();
add(x,y);
}
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
//.....
return 0;
}
双向边直接看块数即可
2.割点
1.双向边
int dfn[N],low[N],tim;
bool flag[N];
void tarjan(int x,int fa)
{
dfn[x]=low[x]=++tim;
int child=0;
for(int i=h[x],v;i;i=e[i].nt)
{
if(!dfn[v=e[i].to])
{
tarjan(v,x);
low[x]=min(low[x],low[v]);
if(low[v]>=dfn[x]&&x!=fa)flag[x]=1;
if(x==fa)child++;
}
else low[x]=min(low[x],dfn[v]);
}
if(child>1&&x==fa)flag[x]=1;
}
3.割边
1.双向边
struct edge
{
int nt,to;
}e[N<<1];
int h[N],id=1;//id 赋初值为 1 !!!
inline void add(const int x,const int y){e[++id].to=y;e[id].nt=h[x];h[x]=id;}
int n,m;
bool cut[M],vis[N];
int tim,dfn[N],low[N];
int co[N],col;
void tarjan(int x,int fa)//x 上一条边
{
dfn[x]=low[x]=++tim;
for(int i=h[x],v;i;i=e[i].nt)
{
if(!dfn[v=e[i].to])
{
tarjan(v,i);
low[x]=min(low[x],low[v]);
if(low[v]>dfn[x])cut[i]=cut[i^1]=1;
}
else if(i!=(fa^1))low[x]=min(low[x],dfn[v]);
}
}
void dfs(int x)
{
co[x]=col;
for(int i=h[x],v;i;i=e[i].nt)
{
if(cut[i]||co[v=e[i].to])continue;
dfs(v);
}
}
signed main()
{
n=read();m=read();
for(int i=1;i<=m;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);//双向边
}
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,0);
for(int i=1;i<=n;i++)if(!co[i])++col,dfs(i);//割边之后连通块 (check ans)
for(int i=1;i<=n;i++)printf("%lld ",co[i]);
return 0;
}
圆方树 点双
struct edge
{
int nt,to;
}e[M],e1[M];
int h[N],id,h1[M],id1;
inline void add(const int x,const int y){e[++id].to=y;e[id].nt=h[x];h[x]=id;}
inline void add1(const int x,const int y){e1[++id1].to=y;e1[id1].nt=h1[x];h1[x]=id1;}
int n,m,q,tot;//tot>n
int dfn[N],low[N],tim;
int st[N],top;
inline void tarjan(int x,int ffa)
{
// putchar('A');
// write(x);putchar(' ');printf("%d",ffa);puts("");
dfn[st[++top]=x]=low[x]=++tim;
for(int i=h[x],v;i;i=e[i].nt)
{
if(!dfn[v=e[i].to])
{
tarjan(v,x),low[x]=mmin(low[x],low[v]);
if(low[v]>=dfn[x])
{
++tot;
add1(tot,x);add1(x,tot);
while(st[top+1]^v)add1(tot,st[top]),add1(st[top--],tot);
}
}
else if(v^ffa)low[x]=mmin(low[x],dfn[v]);
}
}
浙公网安备 33010602011771号