【连通图】双连通模板 Tarjan

比起求无向图关节点的算法,只是多了一个栈,用来储存不存在关节点的所有边,遇到关节点之后弹出所有边进行储存

int dfs(int u, int fa)
{
    int lowu = dfn[u] = ++deep;
    int son = 0;
    for(int i = head[u]; ~i; i = e[i].next) {
        int v = e[i].v;
        Pair p = Pair(u, v);
        if(!dfn[v]) {
            s.push(p);
            son++;
            int lowv = dfs(v, u);
            lowu = min(lowu, lowv);
            if(lowv >= dfn[u]) {
                iscut[u] = 1;
                bcc_cnt++;//从1开始编号的
                bcc[bcc_cnt].clear();
                while(1) {
                    Pair x = s.top(); s.pop();
                    if(bcc_id[x.u] != bcc_cnt) {
                        bcc[bcc_cnt].PB(x.u);
                        bcc_id[x.u] = bcc_cnt;
                    }
                    if(bcc_id[x.v] != bcc_cnt) {
                        bcc[bcc_cnt].PB(x.v);
                        bcc_id[x.v] = bcc_cnt;
                    }
                    if(x.u == u && x.v == v) break;
                }//弹出所有边进行储存,直到遇见了u->v
            }
        }
        else if(dfn[v] < dfn[u] && v != fa) {
            s.push(p);
            lowu = min(lowu, dfn[v]);
        }
    }
    if(fa == -1 && son == 1) iscut[u] = 0;
    return lowu;
}

如果图不连通,还要加上这个:

for(int i = 0; i< n; i++) {
            if(!dfn[i]) dfs(i, -1);
        }//为每个连通图跑一次tarjan
时间: 2024-10-24 22:38:05

【连通图】双连通模板 Tarjan的相关文章

【连通图|双连通】双连通分量 Tarjan

/* * ID: j.sure.1 * PROG: * LANG: C++ */ #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <ctime> #include <cmath> #include <stack> #include <queue> #include <vector&g

双连通模板

1 void dfs(int u,int fa) 2 { 3 dfn[u]=low[u]=++dfs_cut; 4 vs[u]=1; 5 s.push(u); 6 int p=1; ///去重 7 for (int i=0;i<g[u].size();i++) 8 { 9 int v=g[u][i]; 10 if (v==fa&&p) 11 { 12 p=0; 13 continue; 14 } 15 if (!vs[v]) 16 { 17 dfs(v,u); 18 low[u]=m

【强连通】强连通模板 Tarjan

比起双连通的Tarjan我倒是觉得反而简单多了.思想和双连通分量是同一个模式. #include <cstdio> #include <cstring> #include <cstdlib> #include <stack> using namespace std; const int N = 1e5; int dfn[N], scc_id[N]; int deep, scc_cnt; stack <int> s; int dfs(int u)

割点、桥模板以及点双连通、边双连通

一.概念 概念: 1.桥: 如果在图G中删去一条边e后,图G的连通分支数增加,即W(G-e)>W(G),则称边u为G的桥,又称割边或关节边. 2.割点:如果在图G中删去一个结点u后,图G的连通分枝数增加,即W(G-u)>W(G),则称结点u为G的割点,又称关节点. 3.点双连通分量:不含割点的连通子图 4.边双连通分量:不含割边的连通子图 性质: 1.边双连通分量中,任意两点都在某个边环中.(任意两点不一定在点环中) 2.点双连通分量中,任意两点都在某个点环中. 3.点双连通分量不一定是边双连

【连通图|边双连通+缩点】POJ-3177 Redundant Paths

Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K       Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to another field, Bessie and the rest of the herd are forced to cross near the T

POJ3352 Road Construction Tarjan+边双连通

题目链接:http://poj.org/problem?id=3352 题目要求求出无向图中最少需要多少边能够使得该图边双连通. 在图G中,如果任意两个点之间有两条边不重复的路径,称为“边双连通”,去掉任何一条边都是其他边仍然是连通的,也就是说边双连通图中没有割边. 算法设计是:运用tarjan+缩点.对于每一个边双连通分量,我们都可以把它视作一个点,因为low值相同的点处在同一个边双连通分量中,可以简单地思考一下,(u,v)之间有两条可达的路径,dfs一定可以从一条路开始搜索并且从另一条路回去

poj 3177 Redundant Paths(tarjan边双连通)

题目链接:http://poj.org/problem?id=3177 题意:求最少加几条边使得没对点都有至少两条路互通. 题解:边双连通顾名思义,可以先求一下连通块显然连通块里的点都是双连通的,然后就是各个连通块之间的问题. 也就是说只要求一下桥,然后某个连通块桥的个数位1的总数,结果就是(ans+1)/2.为什么是这个结果自行画图 理解一下,挺好理解的. #include <iostream> #include <cstring> #include <cstdio>

【连通图|边双连通+缩点】POJ-3352 Road Construction

Road Construction Time Limit: 2000MS Memory Limit: 65536K Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the roads on the tropical island paradise of Remo

双连通问题

一些定义: 割点集合(割集):在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合. 点连通度:最小割点集合中的顶点数. 割边集合:如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合. 边连通度:最小割边集合中的边数. 点双连通:如果一个无向连通图的点连通度大于1,则称该图是点双连通的,简称双连通或重连通.割点:一个图有割点,当且仅当这个图的点连通度为1,则割点集合的唯一元素被称为