TZOJ 1299/3644: 畅通工程 并查集

1299:

描述

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

输入

测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
注意:两个城市之间可以有多条道路相通,也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。

输出

对每个测试用例,在1行里输出最少还需要建设的道路数目。

样例输入

 

4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0

样例输出

1
0
2
998

 

这题简单,每输入一条道路的x,y,就使用find查找x,y的祖先是否相同,如果不同那么使用merger把x,y合并,最后再计算目前n个结点里面有多少个祖先sum,那么最少还需要sum-1条道路

复制代码
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int f[100001];
 4 struct node{
 5     int x,y;
 6 }; 
 7 node a[100001];
 8 int n,m;
 9 int find(int x)
10 {
11     if(f[x]!=x)f[x] = find(f[x]);
12     return f[x];
13 }
14 void merger(int x,int y)
15 {
16     int fx = find(x);
17     int fy = find(y);
18     f[fx] = fy;
19 }
20 int main()
21 {
22     while(cin>>m)
23     {
24         if(m==0)break;
25         cin>>n;
26         for(int i=1;i<=m;i++)f[i] = i;
27         int x,y;
28         for(int i=1;i<=n;i++)
29         {
30             cin>>a[i].x>>a[i].y;
31         }
32         for(int i=1;i<=n;i++)
33         {
34             if(find(a[i].x)!=find(a[i].y))
35             {
36                 merger(a[i].x,a[i].y);
37             }
38         }
39         int sum = 0;
40         for(int i=1;i<=m;i++)
41             if(f[i]==i)sum++;
42         if(sum==1)cout<<0<<endl;
43         else cout<<sum-1<<endl;
44     }
45      return 0;
46 }
复制代码

 

3644:

描述

 

省政府”畅通工程“的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
 

 

 

输入

 

测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( M< 100, N<=M*(M-1)/2 );随后的 N行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
 

 

 

输出

 

对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出"?"。
 

 

 

样例输入

 

3 3
1 2 1
1 3 2
2 3 4
1 3
2 3 2
0 100

样例输出

 

3
?

 

思路:读入数据的时候先存起来,然后对成本进行从小到大的排序,这样再串通所有路径,这样得到的路径成本一定是最小费用,然后再判断是不是只有一个祖先,是的话那才是把M个结点都串通了

复制代码
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int f[100001];
 4 struct node{
 5     int x,y,l;
 6 }; 
 7 node a[100001];
 8 int n,m;
 9 bool cmp(node a,node b)
10 {
11     return a.l<b.l;
12 }
13 int find(int x)
14 {
15     if(f[x]!=x)f[x] = find(f[x]);
16     return f[x];
17 }
18 void merger(int x,int y)
19 {
20     int fx = find(x);
21     int fy = find(y);
22     f[fx] = fy;
23 }
24 int main()
25 {
26     while(cin>>n>>m)
27     {
28         if(n==0)break;
29         for(int i=1;i<=m;i++)f[i] = i;
30         int x,y,l;
31         for(int i=1;i<=n;i++)
32         {
33             cin>>a[i].x>>a[i].y>>a[i].l;
34         }
35         sort(a+1,a+1+n,cmp);
36         int ans = 0;
37         for(int i=1;i<=n;i++)
38         {
39             if(find(a[i].x)!=find(a[i].y))
40             {
41                 merger(a[i].x,a[i].y);
42                 ans+=a[i].l;
43             }
44         }
45         int sum = 0;
46         for(int i=1;i<=m;i++)
47             if(f[i]==i)sum++;
48         if(sum==1)cout<<ans<<endl;
49         else cout<<"?"<<endl;
50     }
51      return 0;
52 }
复制代码

 

posted @   CRt0729  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示