题目链接
题目分析
最小生成树问题,不过要求得不是路径和,而是使生成树中的最长边最小;
| 细节:
1、结点编号1~N
2、注意题目给的测试数据有BUG;
解题思路
Kruskal算法 + 并查集;
AC程序(C++)
/**********************************
*@ID: 3stone
*@ACM: POJ-1861 Network
*@Time: 18/9/15
*@IDE: VSCode + clang++
***********************************/
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 1010;
struct edge{
int u, v, cost;
edge() {}
edge(int _u, int _v, int _cost) : u(_u), v(_v), cost(_cost) {}
bool operator < (const edge& n) const {//规定优先级,形成小顶堆
return cost > n.cost;
}
};
int N, M;
int far[maxn]; //并查集
vector<edge> route; //保存生成树的边
//寻根
int find_root(int a) {
int root = a;
while(root != far[root]) root = far[root];
while(a != far[a]) {
int cur = a;
a = far[a];
far[cur] = root;
}
return root;
}
int kruskal(priority_queue<edge> E) {
int ans = 0;
int edge_num = 0;
while(!E.empty()) {
edge e = E.top(); E.pop();
int root_u = find_root(e.u);
int root_v = find_root(e.v);
if(root_u != root_v) {
edge_num++;
route.push_back(e); //保存加入的边
far[root_v] = root_u; //合并集合
if(edge_num == N - 1) {
ans = e.cost; //保存最后一个最大边即可;
break;
}
}
}//while
if(edge_num == N - 1) return ans;
else return -1;
}
int main() {
int a, b, cost;
while(scanf("%d %d", &N, &M) != EOF) {
priority_queue<edge> E;
route.clear(); //清空路径
for(int i = 0; i < M; i++) {//输入边信息
scanf("%d%d%d", &a, &b, &cost);
E.push(edge(a, b, cost));
}
for(int i = 1; i <= N; i++) far[i] = i; //初始化并查集
int ans = kruskal(E); //需要先输出最大边,那么就需要保存所有边了吗?
printf("%d\n", ans);
printf("%d\n", route.size());
for(int i = 0; i < route.size(); i++) {
edge e = route[i];
printf("%d %d\n", e.u, e.v);
}
}//while
return 0;
}