[学习笔记]Tarjan

本篇并不适合初学者阅读。

SCC:

1.Tarjan缩点:x回溯前,dfn[x]==low[x]则缩点。

注意:

①sta,in[]标记。

②缩点之后连边可能有重边。

2.应用:

SCC应用范围还是很广的。

基本思路是:Tarjan+topo

DAG是个好东西。

各种判断连通性(传递关系),计数,以及dp转移

感觉90%以上的tarjan都是考SCC

例题:最大半连通子图(这个题注意缩点后的重边)

衍生应用算法:

①2-SAT

②完备匹配的二分图必须边和可行边。

E-DCC

1.Tarjan找桥:x的一个子节点y,dfn[x]<low[y],边就是桥

注意:

①in_edge,对称建边号。不能从in_edge^1出发。但是可以走重边。

然后不经过桥dfs,找E-DCC

2.应用:

①最短路的必经边:建出最短路图,找桥即可。

②例题:poj3694

找出桥边,E-DCC缩点。

对于询问(x,y)x,y不在一个DCC,

找LCA,之后可以往上暴力找路径,干掉桥。

然鹅使用并查集更快。

O(M+N+Qlogn)

V-DCC

1.找割点:dfn[x]<=low[y]不用管重边什么的。

注意:

①搜索树根节点要有两次符合,才是割点。

其实对于割点x,dfn[x]<=low[y]的出点y,这些y一定在不同的DCC中。

缩点:

除了孤立点之外,每个DCC大小至少为2


每个割点属于多个DCC

用栈维护。

如果某个点满足dfn[x]<=low[y]

那么,不断弹出栈顶,直到y弹出。

把这些点和x都放进一个DCC中。(vector存)

可以发现一个x属于多个DCC

缩点的时候,

先把割点设置编号(cnt+1~cnt+tot)cnt是DCC个数

tot是割点个数

循环所有的DCC,循环所有的成员

如果找到割点,就让这个割点和这个DCC连边。

连出一个黑点白点相间的树(黑点可以认为是割点)

例题:

[HNOI2012]矿场搭建

分类讨论即可

KNIGHTS - Knights of the Round Table

性质题,

建立反图。没有仇恨的人连边。

没有出现在任何一个简单奇环中的骑士滚蛋

V-DCC缩点

如果两个骑士DCC不同,一定不能同时出席。(否则在一个奇环中的话,那么两个DCC可以合并。矛盾)

如果一个DCC中有奇环,那么DCC中的所有骑士都可以被一个奇环包含。(可以构造)

综上,一个骑士被包含,因为不能和其他DCC合作,所以必须当且仅当自己的DCC中有奇环

Tarjan+二分图染色判断奇环

附赠福利:

欧拉回路:

void dfs(int x){

for(each son)
if(!vis[i]){

vis[i]=vis[i^1]=1;

dfs(e[i].to)
}

sta[++top]=x;

}

然后sta倒着输出即可。

至于每个点访问多次,可以弧优化减少枚举。

猜你喜欢

转载自www.cnblogs.com/Miracevin/p/9911695.html