关于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]);
	}
}
posted @ 2023-11-21 21:59  PeyNiKge  阅读(18)  评论(0)    收藏  举报