poj3177 Redundant Paths 边双连通分量

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#define eps 1e-6
#define ll __int64
using namespace std;
#define N 1010
#define M 20010

struct node
{
    int v;//下个顶点
    node *next;//下个边结点
};
int n,m,r[N],d[N];//d表示缩点后各顶点的度数
node mem[M];int memp;//存储边结点
node *e[N];
int necc;//原图中边双连通分量的个数
int belong[N];
int low[N],dfn[N];
int vis[N];
int brig[M][2],nbrig;

void addedge(int i,int j)
{
    node *p=&mem[memp++];
    p->v=j;
    p->next=e[i];
    e[i]=p;
}

int root(int a)
{
    if(a!=r[a])
        r[a]=root(r[a]);
    return r[a];
}

void merge(int a,int b)
{
    int ra=root(a);
    int rb=root(b);
    if(ra!=rb)
        r[ra]=rb;
}

void dfs(int i,int father,int dth)
{
    int j,tofa=0;
    node *p;
    vis[i]=1;
    low[i]=dfn[i]=dth;
    for(p=e[i];p!=NULL;p=p->next)
    {
        j=p->v;
        if(vis[j]&&(j!=father||tofa))
            low[i]=min(low[i],dfn[j]);
        if(!vis[j])
        {
            dfs(j,i,dth+1);
            low[i]=min(low[i],low[j]);
            if(low[j]<=dfn[i]) merge(i,j);//i,j在同一个双联通分量
            if(low[j]>dfn[i]) //边i,j是桥
            {
                brig[nbrig][0]=i;
                brig[nbrig++][1]=j;
            }
        }
        if(j==father) tofa=1;
    }
    vis[i]=2;
}

int doubleconne()
{
    int i,k,ncon=nbrig=0;
    dfs(0,-1,1);
    for(i=0;i<n;i++)
    {
        k=root(i);
        if(belong[k]==-1) belong[k]=ncon++;
        belong[i]=belong[k];
    }
    return ncon;
}

void init()
{
    memp=nbrig=0;
    memset(e,0,sizeof e);
    memset(d,0,sizeof d);
    for(int i=0;i<=n;i++)
        r[i]=i;
    memset(vis,0,sizeof vis);
    memset(belong,-1,sizeof belong);
}

int main()
{
    int i,j,k,a,b;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            addedge(a-1,b-1);
            addedge(b-1,a-1);
        }
        necc=doubleconne();
        for(k=0;k<nbrig;k++)
        {
            i=brig[k][0];
            j=brig[k][1];
            d[belong[i]]++;
            d[belong[j]]++;
        }
        int cnt=0;//收缩后叶子结点的个数
        for(i=0;i<necc;i++)
            if(d[i]==1) cnt++;
        printf("%d\n",(cnt+1)/2);
    }
    return 0;
}

poj3177 Redundant Paths 边双连通分量,布布扣,bubuko.com

时间: 2024-10-21 18:42:22

poj3177 Redundant Paths 边双连通分量的相关文章

POJ 3177 Redundant Paths 边双连通分量+缩点

题目链接: poj3177 题意: 给出一张连通图,为了让任意两点都有两条通路(不能重边,可以重点),至少需要加多少条边 题解思路: 分析:在同一个边双连通分量中,任意两点都有至少两条独立路可达,所以同一个边双连通分量里的所有点可以看做同一个点. 缩点后,新图是一棵树,树的边就是原无向图桥. 现在问题转化为:在树中至少添加多少条边能使图变为双连通图. 结论:添加边数=(树中度为1的节点数+1)/2 具体方法为,首先把两个最近公共祖先最远的两个叶节点之间连接一条边,这样可以把这两个点到祖先的路径上

【POJ 3177】Redundant Paths(双连通分量)

求出每个双连通分量缩点后的度,度为1的点即叶子节点.原图加上(leaf+1)/2条边即可变成双连通图. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <map> using namespace std; const int N = 5010; const int M = 10010; struct Edge { int

[POJ3177]Redundant Paths(双连通图,割边,桥,重边)

题目链接:http://poj.org/problem?id=3177 和上一题一样,只是有重边. 如何解决重边的问题? 1.  构造图G时把重边也考虑进来,然后在划分边双连通分量时先把桥删去,再划分,其中桥的一端的割点归入当前正在划分的边双连通分量.这个处理比较麻烦: 2.  在输入图G的边时,若出现重边,则不把重边放入图G,然后在划分边双连通分量时依然用Low划分. 1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓

POJ3177 Redundant Paths 双连通分量

Redundant Paths 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 Tree of Rotten Apples. The cows are now tired of

poj3352 Road Construction &amp; poj3177 Redundant Paths (边双连通分量)题解

题意:有n个点,m条路,问你最少加几条边,让整个图变成边双连通分量. 思路:缩点后变成一颗树,最少加边 = (度为1的点 + 1)/ 2.3177有重边,如果出现重边,用并查集合并两个端点所在的缩点后的点. 代码: /*3352*/ #include<set> #include<map> #include<stack> #include<cmath> #include<queue> #include<vector> #include&

【连通图|边双连通+缩点】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

POJ 3177 Redundant Paths (双连通)

题目地址:POJ 3177 找出各个双连通分量度数为1的点,然后作为叶子节点,那么ans=(叶子结点数+1)/2.需要注意的是有重边. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include

Redundant Paths---poj3177(双连通分量)

题目链接:http://poj.org/problem?id=3177 题意:有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新建多少条路,使得任何两个牧场之间至少有两条独立的路.两条独立的路是指:没有公共边的路,但 可以经过同一个中间顶点. 要先将图 强联通分量缩点, 在无向图中我们称为边双连通分量. 将所有边双连通分量求出来缩成点,就形成了一棵树,我们只要判断树的叶子结点的个数就行了.假设叶子节点的个数是 n  那么 就有 (n+1)

POJ3177:Redundant Paths(并查集+桥)

Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19316   Accepted: 8003 题目链接:http://poj.org/problem?id=3177 Description: In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to anot