浅谈Tarjan缩点(分析+模板)

 昨天一看发现我的博客数量到100篇了,撒花✿✿ヽ(°▽°)ノ✿


根据标题我们也知道,想要在接下来的十分钟不浪费生命

读者需要先行学习Tarjan强联通分量

如果不会的话可以点击这里:

上面这个图中,圆里的是编号,红色的是点的权值,箭头代表边的方向

这个图缩点之后是这样的

符号所表示的东西不变,原来的2,3,4变成了现在的2,原来的5是现在的3

 

是不是感觉没有多难,下面我来带大家看一下具体的实现流程

分为两步:

1.求出图中的强联同分量,并转化为点

2.将转化出来的新的点建成一个新的图

step1:

如何求出强联通分量就不多说了(不会的去看上面的链接)

每一种强联通分量会缩成一个点,这个店的编号我们就定为发现它的顺序,也就是染上的颜色

每一种颜色(一个强联通分量)对应一个点

但是要在中间加一个操作,用来计算一个联通分量的所缩成的点的点权(看注释)

 

复制代码
void Tarjan(int x,int fa){//Tarjan模板     low[x]=dfn[x]=++tot;     sta[++size]=x;     book[x]=1;     for(int e=head1[x];e;e=nxt1[e]){         if(!dfn[to1[e]]){             Tarjan(to1[e],x);             low[x]=min(low[x],low[to1[e]]);         }         else if(book[to1[e]]) low[x]=min(low[x],dfn[to1[e]]);     }     if(dfn[x]==low[x]){         color[x]=++color_cnt;         v2[color_cnt]=v[x];         book[x]=0;         while(sta[size]!=x){             color[sta[size]]=color_cnt;             book[sta[size]]=0;             v2[color_cnt]+=v[sta[size]];//这个点的权值的计算,根据题目来确定             size--;         }         size--;     }     return ; }
复制代码

 

 

step2:
建图的边怎么练一直是个难点,首先可以确定的是因为原来的强连通分量已经变成一个个的点了

所以肯定无法照搬原图

但也不可能自创,所以需要判断,从原来的图上选择那些边

选边的原则是不能是一个强连通分量里的边

也就是说别的边都可以选

那么有的人就问了,缩完点之后不担心友谊重边吗

这很好处理,用邻接矩阵来存(不推荐),或者在之后的程序中标记都可以

特别提到,印的图要用一个新的邻接表来存

而且要连接的不是原来的点,而是两个点被染成的颜色

代码实现的话很简单,循环和dfs都可以,这里我们采用循环(代码量较小)

复制代码
void change(){     for(int i=1;i<=
                    
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信