poj3177--Redundant Paths(边的双连通)

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

一个连通无向图最少加几条边变成双连通图
(缩点后叶子节点(即度数为1)的个数 + 1) / 2

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
/*
一个连通无向图最少加几条边变成双连通图
边的双连通
(缩点后叶子节点(即度数为1)的个数 + 1)/2
*/

const int N = 5005;
const int M = 200005;

struct Edge {
    int to, next;
    bool cut;
} edge[M];
int cnt_edge;
int head[N];
void add_edge(int u, int v)
{
    edge[cnt_edge].to = v;
    edge[cnt_edge].next = head[u];
    edge[cnt_edge].cut = false;
    head[u] = cnt_edge++;
}

int dfn[N]; int idx;
int low[N];
int stk[N]; int top;
int kind[N]; int cnt;
bool in[N];

int bridge;

int n, m;

void tarjan(int u, int pre)
{
    low[u] = dfn[u] = ++idx;
    in[u] = true;
    stk[++top] = u;
    for (int i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        if (v == pre) continue;
        if (!dfn[v])
        {
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if (low[v] > dfn[u])
            {
                bridge++;
                edge[i].cut = true;
                edge[i ^ 1].cut = true;
            }
        }
        else low[u] = min(low[u], dfn[v]);
    }
    if (low[u] == dfn[u])
    {
        cnt++;
        int v;
        do {
            v = stk[top--];
            in[v] = false;
            kind[v] = cnt;
        } while (u != v);
    }
}

int deg[N];
void solve()
{
    for (int u = 1; u <= n; ++u)
    {
        for (int i = head[u]; i != -1; i = edge[i].next)
        {
            if (edge[i].cut) deg[kind[u]]++;
        }
    }
    int leaf = 0;
    for (int i = 1; i <= cnt; ++i)
        if (deg[i] == 1) ++leaf;
    printf("%d
", (leaf + 1) / 2);
}

void init()
{
    memset(head, -1, sizeof head);
    memset(dfn, 0, sizeof dfn);
    memset(deg, 0, sizeof deg);

    top = idx = cnt = cnt_edge = 0;
}

int main()
{
    int a, b;
    while (~scanf("%d%d", &n, &m))
    {
        init();
        for (int i = 0; i < m; ++i)
        {
            scanf("%d%d", &a, &b);
            add_edge(a, b);
            add_edge(b, a);
        }
        tarjan(1, -1);
        solve();
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/wenruo/p/4990779.html