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




原文地址:https://www.cnblogs.com/a2985812043/p/7258408.html