• E


    某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路? 

    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
    
    
         
     
    Huge input, scanf is recommended.

    Hint

    Hint

    解法:
    这是一道应用并查集的题目,可以当作初步学习并查集思想的题目
    关于并查集可以看一下这个博客 http://blog.csdn.net/dellaserss/article/details/7724401/
     1 #include<iostream>
     2 using namespace std;
     3 
     4 int  pre[1050];
     5 bool t[1050];               //t 用于标记独立块的根结点
     6 
     7 int Find(int x)
     8 {
     9     int r=x;
    10     while(r!=pre[r])
    11         r=pre[r];
    12     
    13     int i=x,j;
    14     while(pre[i]!=r)
    15     {
    16         j=pre[i];
    17         pre[i]=r;
    18         i=j;
    19     }
    20     return r;
    21 }
    22 
    23 void mix(int x,int y)
    24 {
    25     int fx=Find(x),fy=Find(y);
    26     if(fx!=fy)
    27     {
    28         pre[fy]=fx;
    29     }
    30 } 
    31 
    32 int main()
    33 {
    34     int N,M,a,b,i,j,ans;
    35     while(scanf("%d%d",&N,&M)&&N)
    36     {
    37         for(i=1;i<=N;i++)          //初始化 
    38             pre[i]=i;
    39         
    40         for(i=1;i<=M;i++)          //吸收并整理数据 
    41         {
    42             scanf("%d%d",&a,&b);
    43             mix(a,b);
    44         }
    45         
    46         
    47         memset(t,0,sizeof(t));
    48         for(i=1;i<=N;i++)          //标记根结点
    49         {
    50             t[Find(i)]=1;
    51         }
    52         for(ans=0,i=1;i<=N;i++)
    53             if(t[i])
    54                 ans++;
    55                 
    56         printf("%d
    ",ans-1);
    57         
    58     }
    59     return 0;
    60 }//dellaserss
    解法2:下面的这个代码是我第一次写这道题时,自己瞎几把乱搞AC的代码,实际思路和并查集的思想很像,只是用了一种很麻烦的办法去实现
     1 #include <iostream>
     2 #include <string.h>
     3 using namespace std;
     4 
     5 const int MAX = 1000 +500;
     6 int Map[MAX][MAX],visit[MAX];
     7 int N,n;
     8 
     9 int main()
    10 {
    11     while(cin>>N)
    12     {
    13         memset(Map,0,sizeof(Map));
    14         memset(visit,0,sizeof(visit));
    15         if(N == 0)
    16             break;
    17         cin>>n;
    18         for(int i=1;i<=n;i++)
    19         {
    20             int x,y;
    21             cin>>x>>y;
    22             if(Map[x][y]!=1)
    23             {
    24 
    25                 Map[x][y] = 1;
    26             }
    27         }
    28 
    29 
    30 
    31 
    32         int Ti = N;
    33         int ti = 0;
    34         for(int i = 1;i<=N;i++)
    35         {
    36             for(int j = 1;j<=N;j++)
    37             {
    38                 if(i == j) continue;
    39                 if(Map[i][j]==1)
    40                 {
    41                     if(visit[i]==0&&visit[j]==0)
    42                     {
    43                         ti++;
    44                         visit[i] = ti;
    45                         visit[j] = ti;
    46                         Ti--;
    47                     }
    48                     else if(visit[i]!=0&&visit[j]==0)
    49                     {
    50                         visit[j] = visit[i];
    51                         Ti--;
    52                     }
    53                     else if(visit[j]!=0&&visit[i]==0)
    54                     {
    55                         visit[i] = visit[j];
    56                         Ti--;
    57                     }
    58                     else if(visit[j]!=0&&visit[i]!=0&&visit[i]!=visit[j])
    59                     {
    60                         int min1 = visit[i] <visit[j]?visit[i]:visit[j];
    61                         int max1 = visit[i] >visit[j]?visit[i]:visit[j];
    62                         Ti--;
    63                         for(int l = 1;l<=N;l++)
    64                             if(visit[l]==max1)
    65                                 visit[l] = min1;
    66                     }
    67                 }
    68             }
    69         }
    70 
    71      
    72 
    73         if(Ti==1)
    74             cout<<0<<endl;
    75         else
    76             cout<<Ti-1<<endl;
    77 
    78     }
    79 
    80 
    81     return 0;
    82 }
    View Code
    
    
    


  • 相关阅读:
    Vivado生成及使用edf文件
    ZYNQ Block Design中总线位宽的截取与合并操作
    Modelsim问题集锦
    Questasim10.6c下载安装教程
    ZYNQ工程PL顶层创建block module报错解决
    Linux自定义应用程序及其菜单图标
    OpenWRT DNS无法解析WAN连接的内网服务器域名
    Wishbone总线从接口转Xilinx MIG (Spartan 6)
    Wishbone总线接口RAM
    Windows系统下将目录挂载为一个磁盘并分配盘符
  • 原文地址:https://www.cnblogs.com/a2985812043/p/7258408.html
Copyright © 2020-2023  润新知