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], Is[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));
    memset(Is, 0, sizeof(Is));
}

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);
    Is[u] = 1;
    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();
            Is[v] = 0;
            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
",(ans+1)/2);

    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4713353.html