tarjan 各类板子集合

 


tarjan大板子(非讲解):

1、普通缩点DGA

void tarjan(int x){
dfn[x]=low[x]=++cntp;
q.push(x);v[x]=1;
for(int i=head[x];i;i=bi[i].next){
int j=bi[i].to;
if(!dfn[j]){
tarjan(j);
low[x]=min(low[x],low[j]);
}
else if(v[j])low[x]=min(low[x],dfn[j]);
}
if(low[x]==dfn[x]){
int p;
num++;//缩点的个数
do{
p=q.top();
q.pop();
zh[p]=num;//zh[i]表示 i对应的缩点之后的点
cntt[num]++;//cntt[i]表示缩点之后i点代表的点的个数
v[p]=0;
}while(x!=p);
}
}
//重建边 很多题需要缩点重建边成一个DGA以后在进行操作
for(int i=1;i<=cnt;i++){
if(zh[bi[i].fr]!=zh[bi[i].to])ad(zh[bi[i].fr],zh[bi[i].to]);
}

2、求割点

void tarjan(int x,int root){
dfn[x]=low[x]=++cntp;
int fl=0;
for(int i=head[x];i;i=bi[i].next){
int j=bi[i].to;
if(!dfn[j]){
tarjan(j);
low[x]=min(low[x],low[j]);
if(low[j]>=dfn[x]){
fl++;
if(x!=root||fl>1)ge[x]=1;
}
}
else low[x]=min(low[x],dfn[j]);
}
}

3、求割边

void tarjan(int x,int id){
dfn[x]=low[x]=++cntp;
for(int i=head[x];i!=-1;i=bi[i].next){
int j=bi[i].to;
if(!dfn[j]){
tarjan(j,i);
low[x]=min(low[x],low[j]);
if(low[j]>dfn[x])bb[i]=bb[i^1]=1;//注意边要从02开始存
}
else if(i!=(id^1))low[x]=min(low[x],dfn[j]);
}
}

4、求边双连通分量

void tarjan(int x,int id){
dfn[x]=low[x]=++cntp;
q.push(x);
for(int i=head[x];i!=-1;i=bi[i].next){
// cout<<i<<' '<<id<<endl;
if(i==(id^1))continue;
int j=bi[i].to;
if(!dfn[j]){
tarjan(j,i);
low[x]=min(low[x],low[j]);
}
else low[x]=min(low[x],dfn[j]);
}
if(dfn[x]==low[x]){和父亲的边是割边,和栈里在他上面的点在一个边双连通分量里面。
num++;
int p;
do{
p=q.top();
q.pop();
zh[p]=num;
}while(p!=x);
}
}

5、点双连通分量

void tarjan(int x){
dfn[x]=low[x]=++cntp;
int fl=0;
for(int i=head[x];i;i=bi[i].next){
int j=bi[i].to;
if(!dfn[j]){
q.push(j);
tarjan(j);
low[x]=min(low[x],low[j]);
if(low[j]>=dfn[x]){
num++;
int p;
do{
p=q.top();
q.pop();
mann[num].ps(p);
}while(p!=j);
mann[num].ps(x);
}
}
else low[x]=min(low[x],dfn[j]);
}
}

END

posted @   lzrG23  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示