zoukankan      html  css  js  c++  java
  • 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[]进行环的判断则会出错,因为一个点可能在多个环内。
    */
  • 相关阅读:
    十分钟学会Java8:lambda表达式和Stream API
    史上最全的Spring Boot Cache使用与整合
    史上最全的Spring Boot Starter开发手册
    深入理解JAVA虚拟机(内存模型+GC算法+JVM调优)
    深入理解Mybatis技术与原理
    c++入门之命名空间存在的意义
    机器学习第一篇——最近邻kNN
    Python学习第十八篇——低耦合函数设计思想
    Python学习第十六篇——异常处理
    Python学习第十五篇——类继承和类实例化
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5935606.html
Copyright © 2011-2022 走看看