无向图的双连通分量

大白书模板,图用前向星存储

int pre[MAXN], iscut[MAXN], bccno[MAXN], dfs_clock, bcc_cnt;
vector<int> bcc[MAXN];

int edge,head[MAXN];
struct edgenode
{
    int to,next;
} G[MAXM];

void add_edge(int x,int y)
{
    G[edge].to=y;
    G[edge].next=head[x];
    head[x]=edge++;
}

struct Edge{
    int u, v;
};

stack<Edge> S;

int dfs(int u, int fa)
{
    int lowu=pre[u]=++dfs_clock;
    int child=0;
    for(int i=head[u];i!=-1;i=G[i].next)
    {
        int v=G[i].to;
        Edge e=(Edge){u, v};
        if(!pre[v])
        {
            S.push(e);
            child++;
            int lowv = dfs(v, u);
            lowu = min(lowu, lowv);
            if(lowv>=pre[u])
            {
                iscut[u]=true;
                bcc_cnt++;
                bcc[bcc_cnt].clear();
                for(;;)
                {
                    Edge x=S.top(); S.pop();
                    if(bccno[x.u] != bcc_cnt)
                    {
                        bcc[bcc_cnt].push_back(x.u);
                        bccno[x.u] = bcc_cnt;
                    }
                    if(bccno[x.v] != bcc_cnt)
                    {
                        bcc[bcc_cnt].push_back(x.v);
                        bccno[x.v] = bcc_cnt;
                    }
                    if(x.u == u && x.v == v) break;
                }
            }
        } else
        if(pre[v] < pre[u] && v != fa)
        {
            S.push(e);
            lowu = min(lowu, pre[v]);
        }
    }
    if(fa < 0 && child == 1) iscut[u] = 0;
    return lowu;
}

void find_bcc(int n)
{
    memset(pre, 0, sizeof(pre));
    memset(iscut, 0, sizeof(iscut));
    memset(bccno, 0, sizeof(bccno));
    dfs_clock = bcc_cnt = 0;
    for(int i=0; i<n; i++){
        if(!pre[i]) dfs(i, -1);
    }
}
时间: 2024-08-07 21:17:16

无向图的双连通分量的相关文章

hdu3844 Mining Your Own Business,无向图的双连通分量

点击打开链接 无向图的双连通分量 #include<cstdio> #include<stack> #include<vector> #include<map> #include<algorithm> #include<cstring> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; typedef long lo

连通分量 无向图的割顶和桥 无向图的双连通分量 有向图的强连通分量

时间戳 dfs_clock :说白了就是记录下访问每个结点的次序.假设我们用 pre 保存,那么如果 pre[u] > pre[v], 那么就可以知道先访问的 v ,后访问的 u . 现在给定一条边, (u, v), 且 u 的祖先为 fa, 如果有 pre[v] < pre[u] && v != fa, 那么 (u, v) 为一条反向边. 1 求连通分量: 相互可达的节点称为一个连通分量: #include <iostream> #include <cstd

hdu Caocao&#39;s Bridges(无向图边双连通分量,找出权值最小的桥)

1 /* 2 题意:给出一个无向图,去掉一条权值最小边,使这个无向图不再连同! 3 4 tm太坑了... 5 1,如果这个无向图开始就是一个非连通图,直接输出0 6 2,重边(两个节点存在多条边, 权值不一样) 7 3,如果找到了桥的最小权值为0,也就是桥上的士兵数为0,那么还是要最少派一个 8 士兵过去炸掉桥! 9 10 思路:假设每两个节点最多只有一条边进行相连! 11 进行tarjan算法,如果该算法调用了超过2次,说明这个原图就是不连通的! 12 否则在tarjan算法中将桥存起来!然后

图论--无向图点双连通分量模板

对于一个无向图,如果一个点集,它内部的任意一个点对之间,至少有两条点完全不重复的路径,那么这个点集就是原图的一个点双连通分量,而点双联通分量之间是由割点隔开,割点就是如果删去这个点,原图的连通块数会增加,那么这个点就是割点. 通过tarjan算法,我们可以用一次 dfs 标记出所有的割点以及所有双连通分量. 注释版: 1 #include<stdio.h> 2 #include<string.h> 3 #include<stack> 4 #include<algo

UVALive - 3523 Knights of the Round Table(无向图的双连通分量)

题目大意:有n个骑士经常举行圆桌会议,每次圆桌会议至少要有3个骑士参加(且每次参加的骑士数量是奇数个),且所有互相憎恨的骑士不能坐在圆桌旁的相邻位置,问有多少个骑士不可能参加任何一个会议 解题思路:以骑士为点建立无向图G.如果两个骑士可以相邻(即他们并不互相憎恨),即可连一条边. 则题目就转化为求不在任何一个简单奇圈上的结点个数 首先,圈就是一个双连通的分量,所以第一件事就是将所有的双连通分量求出来,接着再判定这个双连通分量是不是奇圈 奇圈的判定就是用二分图染色判定,如果某个圈能被二分图染色,那

poj 2942 Knights of the Round Table(无向图的双连通分量+二分图判定)

#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #

无向图的割顶和桥,无向图的双连通分量入门详解及模板 -----「转载」

https://blog.csdn.net/stillxjy/article/details/70176689 割顶和桥:对于无向图G,如果删除某个节点u后,连通分量数目增加,则称u为图的割顶:如果删除某条边后,连通分量数目增加,则称该边为图的桥.对于连通图删除割顶或桥后都会使得图不再连通 以下我,我们利用dfs的性质来快速找出一个连通图中的所有的割顶和桥 首先我们要引入”时间戳”这个概念: 时间戳:表示在进行dfs时,每个节点被访问的先后顺序.每个节点会被标记两次,分别用pre[],和post

UVALive-5135 Mining Your Own Business (无向图的双连通分量)

题目分析:在一张无向图中,将一些点涂上黑色,使得删掉图中任何一个点时,每个连通分量至少有一个黑点.问最少能涂几个黑点,并且在涂最少的情况下有几种方案. 题目分析:显然,一定不能涂割点.对于每一个连通分量,如果有1个割点,则必须涂上分量内除割点之外的任意一个点,如果有多个(2个及以上)割点,则这个分量不需要涂色.如果整张图都没有割点,那么任选两个点涂色即可,之所以要涂两个,是要防止删掉的电恰是黑点的情况. 代码如下: # include<iostream> # include<cstdio

UVALive 3523 Knight of Round Table 圆桌骑士 (无向图点双连通分量)

由于互相憎恨的骑士不能相邻,把可以相邻的骑士连上无向边,会议要求是奇数,问题就是求不再任意一个简单奇圈上的结点个数. tarjan直接套以前写的,结果就错了,要特别注意把边加入栈的时间...还不是很理解这个算法 #include<bits/stdc++.h> using namespace std; #define bug(x) cout<<#x<<'='<<x<<endl; const int maxv = 1000+5; const int

无向图的双连通分量(tarjan模板)

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<stack> #include<vector> using namespace std; #define maxn 7500 #define inf 0x3f3f3f3f int n,m; int g[maxn][maxn]; int clock; int low[max