【题目来源】
https://www.acwing.com/problem/content/1140/
【题目来源】
有一张城市地图,图中的顶点为城市,编号为 1∼n,无向边 代表两个城市间的连通关系,边上的权值为在这两个城市之间修建高速公路的造价,研究后发现,这个地图有一个特点,即任何一对城市都是连通的。
现在的问题是,要修建若干高速公路把所有城市联系起来,问如何设计可使得工程的总造价最少?
【输入格式】
第一行包含两个整数 n 和 e,分别表示城市个数和无向边个数。
接下来 e 行,每行包含三个整数 i,j,w,表示在城市 i 和城市 j 之间修建公路的造价为 w。
城市编号从 1 开始。
【输出格式】
共 n−1 行,每行为两个城市的编号,表明在这两个城市间建一条高速公路。
本题答案不一定唯一,输出任意一种最优方案即可,方案中边和点的顺序可以任意选择。
【数据范围】
1≤n≤100,
1≤e≤1000,
1≤w≤10000
数据保证不含重边和自环。
【输入样例】
5 8
1 2 2
2 5 9
5 4 7
4 1 10
1 3 12
4 3 6
5 3 3
2 3 8
【输出样例】
1 2
2 3
3 4
3 5
【算法分析】
● 最小生成树问题,在结点数量较多时,适合采用 Kruskal 算法求解。
● Kruskal算法模板题详见:
https://blog.csdn.net/hnjzsyjyj/article/details/139652267
https://blog.csdn.net/hnjzsyjyj/article/details/139606429
● 并查集
https://blog.csdn.net/hnjzsyjyj/article/details/126455868
https://blog.csdn.net/hnjzsyjyj/article/details/117869180
【算法代码】
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
int pre[maxn];
int n,m;
struct edge {
int u,v;
int cost;
} e[maxn*maxn]; //keypoint
bool cmp(edge x, edge y) {
return x.cost<y.cost;
}
int find(int x) { //DSU's find
if(x!=pre[x]) pre[x]=find(pre[x]);
return pre[x];
}
int main() {
cin>>n>>m;
for(int i=0; i<m; i++) {
int u,v,cost;
cin>>u>>v>>cost;
e[i]= {u,v,cost};
}
for(int i=1; i<=n; i++) pre[i]=i;
sort(e,e+m,cmp);
for(int i=0; i<m; i++) {
int fx=find(e[i].u);
int fy=find(e[i].v);
if(fx!=fy) {
pre[fy]=fx;
cout<<e[i].u<<" "<<e[i].v<<endl;
}
}
return 0;
}
/*
in:
5 8
1 2 2
2 5 9
5 4 7
4 1 10
1 3 12
4 3 6
5 3 3
2 3 8
out:
1 2
2 3
3 4
3 5
*/
【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/139652267
https://www.acwing.com/solution/content/78311/
https://blog.csdn.net/hnjzsyjyj/article/details/139650721