poj 3177 Redundant Paths (双连通)

来源:互联网 发布:做豆浆用什么机器知乎 编辑:程序博客网 时间:2024/05/24 06:13

http://poj.org/problem?id=3177

One visualization of the paths is: 

   1   2   3   +---+---+         |   |       |   | 6 +---+---+ 4      / 5     /     /  7 +
Building new paths from 1 to 6 and from 4 to 7 satisfies the conditions. 
   1   2   3   +---+---+     :   |   |   :   |   | 6 +---+---+ 4      / 5  :     /     :    /      : 7 + - - - - 
Check some of the routes: 
1 – 2: 1 –> 2 and 1 –> 6 –> 5 –> 2 
1 – 4: 1 –> 2 –> 3 –> 4 and 1 –> 6 –> 5 –> 4 
3 – 7: 3 –> 4 –> 7 and 3 –> 2 –> 5 –> 7
 
Every pair of fields is, in fact, connected by two routes. 

ζёСяêτ - 小優YoU  的解析很明白的哦,讲述的太明白了

少在缩点树上增加多少条树边,使得这棵树变为一个双连通图”。

首先知道一条等式:

若要使得任意一棵树,在增加若干条边后,变成一个双连通图,那么

至少增加的边数 =( 这棵树总度数为1的结点数 + 1 )/ 2


 http://blog.csdn.net/lyy289065406/article/details/6762370


#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <cmath>#include <cstdlib>#include <limits>#include <queue>#include <stack>#include <vector>#include <map>using namespace std;#define N 5005#define INF 0xfffffff#define PI acos (-1.0)#define EPS 1e-8vector <vector <int> > G;int n, m, Time, ans, cnt, top;int low[N], dfn[N], ft[N], f[N], eg[N], Stack[N];void Init ();void tarjan (int u, int fa);void solve ();int main (){    while (~scanf ("%d%d", &n, &m))    {        int a, b;        Init ();        while (m--)        {            scanf ("%d%d", &a, &b);            G[a].push_back (b);            G[b].push_back (a);        }        solve ();    }    return 0;}void Init (){    G.clear ();    G.resize (n+1);    memset (low, 0, sizeof (low));    memset (dfn, 0, sizeof (dfn));    memset (Stack, 0, sizeof (Stack));    memset (f, 0, sizeof (f));    memset (ft, 0, sizeof (ft));    Time = top = ans = cnt = 0;}void tarjan (int u, int fa){    low[u] = dfn[u] = ++Time;    Stack[top++] = u;    f[u] = fa;    int len = G[u].size (), v, k = 0;    for (int i=0; i<len; i++)    {        v = G[u][i];        if (v == fa && !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 (low[u] == dfn[u])    {        do        {            v = Stack[--top];            ft[v] = cnt;        }while (u != v);        cnt++;    }}void solve (){    int deg[N] = {0};    for (int i=1; i<=n; i++)        if (!low[i]) tarjan (i, i);    for (int i=1; i<=n; i++)    {        int v = f[i];        if (ft[i] != ft[v])            deg[ft[i]]++, deg[ft[v]]++;//计算叶子节点的度    }    for (int i=0; i<cnt; i++)        if (deg[i] == 1) ans++;//度为1    printf ("%d\n", (ans+1)/2);}


0 0
原创粉丝点击