标签:parent 交叉路口 int kruskal 算法 道路 都市 find 边权
题目:繁忙的大都市
题目链接:https://ac.nowcoder.com/acm/problem/20245
题意:有n个交叉路口和m条双向道路,每条道路有边权。现在要改造道路,要求如下:
- 改造的道路要能把所有交叉路口直接或间接连通起来。
- 在1的前提下,改造的道路尽量少。
- 在1,2的前提下,改造的道路中最大的边权尽量小。
输入描述:
第一行给出交叉路口数n(1 <= n <= 300)和道路数m(1 <= m <= 10000)。
接下来m行,每行三个整数u, v, c表示交叉路口u和v之间有一条边权为c的无向边。
输出描述:
两个整数s, max。表示改造的道路的数目和改造的道路中的最大边权。
样例输入:
4 5
1 2 3
1 4 5
2 4 7
2 3 6
3 4 8
样例输出:
3 6
样例解释:选择第1,2,4三条边,边权分别为3,5,6,最大边权为6。
题目分析:题目要选定边使得所有点连通,且边数最少,且边权最大值尽量小,最小生成树刚好具有这些性质。可以使用kruskal算法求解。
解题步骤:
- 将所有边按权值从小到大排序。
- 从小到大枚举所有边,若边的两个端点不连通,则选定该边,并合并两个边所在的集合。当选定的边数为n – 1时,则说明此时已构成一棵树,此时的边权即为选定的边的最大边权。
AC代码:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 310, M = 10010;
struct st{
int x, y, z;
bool operator < (const st &X) const{
return z < X.z;
}
}a[M];
int n, m, parent[N];
int find(int x){
if(x != parent[x]) parent[x] = find(parent[x]);
return parent[x];
}
void Union(int x, int y){
parent[find(x)] = find(y);
}
void solve(){
scanf("%d %d", &n, &m);
for(int i = 1;i <= n;i++) parent[i] = i;
for(int i = 1;i <= m;i++) scanf("%d %d %d", &a[i].x, &a[i].y, &a[i].z);
sort(a + 1, a + 1 + m);
int cnt = 0, ans = 0;
for(int i = 1;i <= m;i++){
if(find(a[i].x) != find(a[i].y)){
Union(a[i].x, a[i].y);
ans = a[i].z;
cnt++;
if(cnt == n - 1) break;
}
}
printf("%d %d\n", n - 1, ans);
}
int main(void){
solve();
return 0;
}
时间复杂度:O(mlogm)。
空间复杂度:O(n + m)。
标签:parent,交叉路口,int,kruskal,算法,道路,都市,find,边权 来源: https://www.cnblogs.com/www-cnblogs-com-lixuanta/p/15579764.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。