输入格式: 第一行包含两个整数n和m,n为关系网中的人数。 编号从1至n,刘老板是第1位,校长是第n位。M表示刘老板的关系网中有M个关系。(3 <n= 30, 3<=m <=1000) 接下来有m行。每行包含三个整数A、B和C,意思是A和B之间存在关系,如果A向B或B向A求助,刘老板将支付C元。 输出格式: 在你尽了最大努力后,输出Boss Liu要花的最少的钱。如果Boss Liu不能把他的孩子送到大学,就打印“Fail”。c++
时间: 2024-03-12 09:43:47 浏览: 196
这是一个最小生成树的问题,可以使用Kruskal算法或Prim算法求解。以下是Kruskal算法的实现:
```c++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Edge {
int u, v, w;
};
bool cmp(const Edge& a, const Edge& b) {
return a.w < b.w;
}
int find(vector<int>& parent, int x) {
if (parent[x] != x) {
parent[x] = find(parent, parent[x]);
}
return parent[x];
}
void unite(vector<int>& parent, vector<int>& rank, int x, int y) {
int px = find(parent, x), py = find(parent, y);
if (px == py) {
return;
}
if (rank[px] < rank[py]) {
parent[px] = py;
} else {
parent[py] = px;
if (rank[px] == rank[py]) {
rank[px]++;
}
}
}
int kruskal(int n, vector<Edge>& edges) {
vector<int> parent(n + 1), rank(n + 1, 0);
for (int i = 1; i <= n; i++) {
parent[i] = i;
}
sort(edges.begin(), edges.end(), cmp);
int cnt = 0, ans = 0;
for (int i = 0; i < edges.size(); i++) {
int u = edges[i].u, v = edges[i].v, w = edges[i].w;
if (find(parent, u) == find(parent, v)) {
continue;
}
unite(parent, rank, u, v);
ans += w;
cnt++;
if (cnt == n - 1) {
break;
}
}
if (cnt < n - 1) {
return -1;
} else {
return ans;
}
}
int main() {
int n, m;
cin >> n >> m;
vector<Edge> edges(m);
for (int i = 0; i < m; i++) {
cin >> edges[i].u >> edges[i].v >> edges[i].w;
}
int ans = kruskal(n, edges);
if (ans == -1) {
cout << "Fail" << endl;
} else {
cout << ans << endl;
}
return 0;
}
```
在这个实现中,我们定义了一个结构体Edge来表示边,其中包含三个属性:起点、终点和权值。我们还定义了一个比较函数cmp,用于将边按权值从小到大排序。在kruskal函数中,我们首先初始化每个节点的父节点为自己,然后将所有边按权值从小到大排序。接着从小到大枚举每条边,如果它的两个端点不在同一个连通块内,则将它们合并,并将边的权值累加到答案中。最后如果生成树的边数小于n-1,则说明无法将所有节点连通,打印“Fail”,否则打印答案。
阅读全文