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

题目链接:http://poj.org/problem?id=3177

题意:有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走。现已有m条路,求至少要新建多少条路,使得任何两个牧场之间至少有两条独立的路。两条独立的路是指:没有公共边的路,但

可以经过同一个中间顶点。

要先将图 强联通分量缩点, 在无向图中我们称为边双连通分量。

将所有边双连通分量求出来缩成点,就形成了一棵树,我们只要判断树的叶子结点的个数就行了。假设叶子节点的个数是 n  那么 就有 (n+1)/2 条边就能将这个图变成没有桥的 双连通图,判断一个点是否是叶子节点

只要判断这个点的度就行了,度为 1 的点就是叶子节点。

因此我们只需将叶子节点连在一起就可以了,需要建立(叶子节点的个数+1)/ 2;

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <cstring>
using namespace std;
#define INF 0xfffffff
#define N 5100
int low[N], dfn[N], f[N], block[N],du[N];
vector<vector<int> > G;
int n, Time, m, cnt;
stack<int>sta;
void Init()
{
    G.clear();
    G.resize(n+1);
    Time = cnt = 0;
    memset(low, 0, sizeof(low));
    memset(dfn, 0, sizeof(dfn));
    memset(du, 0, sizeof(du));
    memset(f, 0, sizeof(f));
}

void Tarjan(int u, int father)
{
    f[u] = father;
    dfn[u] = low[u] = ++Time;
    int len = G[u].size(), v, k=0;
    sta.push(u);
    for(int i=0; i<len; i++)
    {
        v = G[u][i];
        if(v == father && !k)
        {
            k++;
            continue;
        }
        if(!dfn[v])
        {
            Tarjan(v, u);
            low[u] = min(low[u], low[v]);
        }
        else
        {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(dfn[u] == low[u])
    {
        do
        {
            v = sta.top();sta.pop();
            block[v] = cnt;
        }while(u!=v);
        cnt++;
    }
}

int main()
{
    int a, b;
    while(scanf("%d %d", &n, &m)!=EOF)
    {
        Init();
        while(m--)
        {
            scanf("%d %d", &a, &b);
            G[a].push_back(b);
            G[b].push_back(a);
        }
        for(int i=1; i<=n; i++)
            if(!dfn[i])
                Tarjan(i,-1);
        for(int i=1; i<=n; i++)
        {
            int v = f[i];
            if(v == -1)
            {
                continue;
            }
            if(block[i] != block[v])
            {
                du[block[i] ]++;
                du[block[v] ]++;
            }
        }
        int ans = 0;
        for(int i=0; i<cnt; i++)
        {
            if(du[i]==1)
                ans++;
        }
        printf("%d\n",(ans+1)/2);

    }
    return 0;
}

时间: 2024-07-29 01:08:29

Redundant Paths---poj3177(双连通分量)的相关文章

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-

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 ┓┏┓┏┓

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

POJ 3177 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 often being forc

Redundant Paths——构造双连通图

题目链接 题意: 有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新建多少条路,使得任何两个牧场之间至少有两条独立的路.两条独立的路是指:没有公共边的路,但可以经过同一个中间顶点.该图中为连通图 题解: 题意转换一下: 就是给了一个连通图,问加多少条边可以变成边双连通. 双连通图 我们将原图先缩点, 可以得到一棵树.然后我们统计叶子节点数目leaf(即度为1的点), 最小的加边数即(leaf+1)/2 (成对加边) 考虑重边 代码: #i

LUOGU P2860 [USACO06JAN]冗余路径Redundant Paths (双联通,缩点)

传送门 解题思路 刚开始是找的桥,后来发现这样不对,因为一条链就可以被卡.后来想到应该缩点后找到度数为1 的点然后两两配对. #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<set> using namespace std; const int MAXN = 5005; const int MAXM = 10005; inline i

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