Redundant Paths

【题目描述】

现有F(1 <= F <= 5000)个牧场,任何两个牧场之间至少有一条路,但奶牛们至少需要两条。
给定现有的R(F-1 <= R <= 10000)条直接连接两个牧场的路,计算至少需要新建多少条直接连接两个牧场的路,才能使得任何两个牧场之间至少有两条独立的路(两条独立的路是指没有公共边的路)。

【输入描述】

第一行输入两个数F、R;

接下来R行,每行输入两个数,表示存在一条路直接连接这两个牧场。

【输出描述】

输出一个数,表示答案。

【输入样例】

7 7

1 2

2 3

3 4

2 5

4 5

5 6

5 7

【输出样例】

2

【数据范围及提示】

样例如下:

   1     2     3
   +-----+-----+

         |     |

         |     |
6  +-----+-----+ 4
        / 5
      /
    /
7 +

分别在1号牧场和6号牧场、4号牧场和7号牧场之间建路:

   1     2     3
   +-----+-----+

   |     |     |

   |     |     |
6  +-----+-----+ 4
        / 5    |
      /        | 
    /          | 
7 +-------------

源代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Node
{
    int To,Next;
}Edge[10001];
int N,M,Num,Number,i[5001],j[5001],Head[5001];
bool Map[5001][5001];
void Add(int t1,int t2) //边表。
{
    Edge[++Num].To=t2;
    Edge[Num].Next=Head[t1];
    Head[t1]=Num;
}
void Tarjan(int T,int Father) //Tarjan改版。
{
    i[T]=j[T]=++Number;
    for (int a=Head[T];a;a=Edge[a].Next)
    {
        int t=Edge[a].To;
        if (!j[t])
        {
            Tarjan(t,T);
            i[T]=min(i[T],i[t]);
        }
        else
          if (t!=Father) //无向图,不是直系父亲才符合条件。
            i[T]=min(i[T],j[t]);
    }
}
void Solve()
{
    int Ans(0),Sum[5001]={0};
    for (int a=1;a<=N;a++)
      for (int b=Head[a];b;b=Edge[b].Next)
      {
        int t=Edge[b].To;
        if (i[t]!=i[a]) //不在一环之内便为桥。
          Sum[i[a]]++;
      }
    for (int a=0;a<=N;a++)
      if (Sum[a]==1) //树度数为1的节点数统计。
        Ans++;
    printf("%d
",(Ans+1)>>1); //防止奇数。
}
int main()
{
    while (scanf("%d%d",&N,&M)!=EOF)
    {
        Num=Number=0; //这令人恶心的初始化,为什么POJ的题要多数据啊啊啊!
        memset(j,0,sizeof(j));
        memset(Map,0,sizeof(Map));
        memset(Head,0,sizeof(Head));
        for (int a=0;a<M;a++)
        {
            int t1,t2;
            scanf("%d%d",&t1,&t2);
            if (!Map[t1][t2]) //各点之间只有一条直连边。
            {
                Add(t1,t2);
                Add(t2,t1);
                Map[t1][t2]=Map[t2][t1]=true;
            }
        }
        Tarjan(1,1);
        Solve();
    }
    return 0;
}

/*
    解题思路:
        题目中要求桥数,可以先找出图中的双连通分量,进行缩点,因为在双连通分量中,每个点都已经有两条路了。
        这样就可以建成一个无环图,再找出其中度数为1的节点,数量/2即可。
        如果只利用i[]进行环的判断则会出错,因为一个点可能在多个环内。
*/
原文地址:https://www.cnblogs.com/Ackermann/p/5935606.html