zoukankan      html  css  js  c++  java
  • HDU

    Problem Description
    某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路? 
     
    Input
    测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。 
    注意:两个城市之间可以有多条道路相通,也就是说
    3 3
    1 2
    1 2
    2 1
    这种输入也是合法的
    当N为0时,输入结束,该用例不被处理。 
     
    Output
    对每个测试用例,在1行里输出最少还需要建设的道路数目。 
     
    Sample Input
    4 2
    1 3
    4 3
    3 3
    1 2
    1 3
    2 3
    5 2
    1 2
    3 5
    999 0
    0
     
    Sample Output
    1
    0
    2
    998
     
    一道经典的并查集模板题
    AC代码如下:(仅供参考)
     
     1 #include<stdio.h>
     2 int p[1000]; //用于描述没个数的上一级,保存当前坐标的上一级,上司
     3 int find(int x)//用于查找 x 的老大,掌门人
     4 {
     5     int r=x,t,i,j; 
     6     while(p[r]!=r) //最后r即使x的老大
     7         r=p[r];
     8     t=x;
     9     while(p[t]!=r) //这是利用已知的老大的坐标,压缩路径,将老大所有的手下的的手下的手下.....全部归到只是老大的下一级,为了方便各个小弟查询老大
    10     {
    11         i=p[t];
    12         p[t]=r;
    13         t=i;
    14     }
    15     return r;//返回老大的坐标
    16 }
    17 
    18 
    19 int he(int x,int y)//用于将两个集合合并在一起
    20 {
    21     if(find(x)!=find(y))//查询两个数的老大,如果不同老大,将x的老大变成y的老大
    22     {
    23         p[find(y)]=p[find(x)];
    24         return 1; //返回1用于题目计算需要建的路(打架的次数)
    25     }
    26     return 0;
    27 }
    28 
    29 int main()
    30 {
    31     int n,m,x,y,i;
    32     while(~scanf("%d%d",&n,&m)&&n)
    33     {
    34         int s=n-1;//开始若有n个点,则需要修建n-1条路(打n-1次架)
    35         for(i=1;i<=n;i++)//初始化,把所有点都初始化成自己是自己的老大,自成一派
    36             p[i]=i;
    37         for(i=1;i<=m;i++)
    38         {
    39             scanf("%d%d",&x,&y);
    40             if(he(x,y)==1)s--;//返回1 则表示两个不同小弟是不同的老大,打了一架后,则需要打s-1次架。
    41         }
    42         /*
    43             计算s还可以用,此时每个门派(集合)都归纳好了,开始看看有多少个不同的集合,即看看有多少个不同的老大,根据有多少个老大,这是
    44             在开始看看要打多少次架(帮派间的斗争!!)有n个老大就要打n-1次架 (有n个集合就要n-1次修路)
    45             可以用一个数组存储根,在查询有多少个根!
    46                 
    47         */
    48         printf("%d
    ",s);
    49     }
    50 }
    View Code

     自己敲一遍

     1 #include<cstdio>
     2 #include<algorithm>
     3 
     4 using namespace std;
     5 
     6 int p[1100];
     7 
     8 int Find(int x)
     9 { 
    10     int r = x, t, i;
    11 
    12     while(p[r] != r)
    13         r = p[r];
    14 
    15     t = x;
    16 
    17     while(p[t] != r)
    18     {
    19         i = p[t];
    20         p[t] = r;
    21         t = i;
    22     }
    23 
    24     return r;
    25 }
    26 
    27 int  QQ(int x, int y)
    28 {
    29     if (Find(x) != Find(y))
    30     {
    31         p[Find(y)] = p[Find(x)];
    32         return 1;
    33     }
    34     return 0;
    35 }
    36 
    37 int main()
    38 {
    39     int n;
    40 
    41     while (scanf ("%d", &n), n != 0)
    42     {
    43         int i, m, num = n-1;
    44 
    45         for (i = 1; i <= n; i++)
    46             p[i] = i;
    47 
    48         scanf ("%d", &m);
    49 
    50         int x, y;
    51 
    52         for (i = 0; i < m ;i++)
    53         {
    54             scanf ("%d %d", &x, &y);
    55                 if (QQ(x, y) == 1)
    56                 num--;
    57 
    58         }
    59         printf ("%d
    ", num);
    60     }
    61     return 0;
    62 }
     
    View Code
  • 相关阅读:
    齐次和线性
    数组指针/指针数组
    坐标转换矩阵
    【转】GMM与K-means聚类效果实战
    利用虚函数实现多态的方式:动态绑定
    类型限定符volatile
    《剑指offer》查找二维数组内元素 c++
    windows下使用命令行编译、链接C++源文件
    关于该博客的美化
    vimium快捷键修改
  • 原文地址:https://www.cnblogs.com/Aa948766160/p/5749879.html
Copyright © 2011-2022 走看看