tarjan(缩点)
Posted sky-zxz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tarjan(缩点)相关的知识,希望对你有一定的参考价值。
刚做了两道tarjan缩点的题,新学的算法总结一下。
推荐题:(难度单调递增)
[HAOI2006]受欢迎的牛
[USACO5.3]校园网Network of Schools
间谍网络
这里不教tarjan,要学的找别的博客吧。
总结:tarjan 简单来说 算法过程 就是找环或单独的点,这就可以构成强联通分量。
代码如下:
void tarjan(int u){ low[u]=dfn[u]=++cnt; stk[++top]=u; vis[u]=1; for(register int i=head[u];i;i=edge[i].next){ int v=edge[i].to; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]){ co[u]=++col; vis[u]=0; while(stk[top]!=u){ vis[stk[top]]=0; co[stk[top]]=col; top--; } top--; } }
缩点也很简单,根据col重新建个图就行了。
tarjan缩点题的一些特征和突破口:
1.一般tarjan缩点的题会给你具有传递性的图,利用传递性可以省略掉一些点,例如:如果a喜欢b,b喜欢c,那么a就喜欢c。假设c又喜欢a,这就可以构成一个强连通分量,缩点即可,没错,这就是“受欢迎的牛”。
2.点的入度和出度是很重要的,很多题就围绕这这个东西去变式,关注点的入度和出度,往往会找到突破口。
3.有的题需要记录一些强连通分量内的数据
(1)可以在同一强连通分量中的点出栈的过程中更新,这样比较方便简单。
(2)也可以在主程序中再次for循环去更新,那样就比较麻烦了,时间复杂度和空间复杂度都得增加,然而我第一次打这类题就是这么操作的,代码90行。
反思:还是理解不够深,我的tarjan总是打错一点,然后又去修改,还是得多模拟一下tarjan缩点的过程。
以上是关于tarjan(缩点)的主要内容,如果未能解决你的问题,请参考以下文章
洛谷 P2194 HXY烧情侣Tarjan缩点 分析+题解代码