关于tarjan
每次写边双总要调很久,就记一个模板罢。
其实有一个前不久写的板子,但找不到是哪个题了。
这个板子是之前模拟赛调出来的,今天看了一下,认为很好,就用这个罢。
void tj(int u, int F){
dfn[u] = low[u] = ++cnt;
Son(G, u){
if(!dfn[v]) tj(v, ik ^ 1), low[u] = min(low[u], low[v]);
else if(ik != F) low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u] && u != 1)
bk[F] = bk[F ^ 1] = 1;
// 如果一个节点走不出他自己的子树,那他上面的一条边就是割边。
}
点双基本没写过,本来想写和上面相似的代码,但是调不出来,就用算阶上的罢。
void tj(int u, int F){
dfn[u] = low[u] = ++cnt;
int tot = 0;
Son(G, u){
if(v == F) continue;
if(!dfn[v]){
tj(v, u);
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u]){
tot++;
if(u != rt || tot > 1) bj[u] = 1;
}
}
else low[u] = min(low[u], dfn[v]);
}
}
算阶上的边双
void tj(int u, int F){
dfn[u] = low[u] = ++cnt;
Son(G, u){
if(!dfn[v]){
tj(v, ik ^ 1);
low[u] = min(low[u], low[v]);
if(low[v] > dfn[u]){
bk[ik] = bk[ik ^ 1] = 1;
}
}
else if(ik != F) low[u] = min(low[u], dfn[v]);
}
}

浙公网安备 33010602011771号