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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现