题意:给定一个n个点m条边的无向图,找一颗苗条度(最大边减最小边)最小的生成树。
思路:假设苗条度最小的这棵树的最小边为a,若要使苗条度最小,答案一定是以a为最小边的一颗最小生成树,所以可以考虑枚举最小边,计算出苗条度并更新答案。
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<map> #include<set> #define eps 1e-6 #define LL long long using namespace std; const int maxn = 100 + 5; const int maxm = 10000; const int INF = 0x3f3f3f3f; int n, m; int u[maxm], v[maxm], w[maxm], p[maxn], r[maxm]; bool cmp(const int i, const int j) { return w[i] < w[j]; } int find_p(int x) { return p[x] == x ? x : p[x] = find_p(p[x]); } int Kruscal(int edge_id) { for(int i = 1; i <= n; i++) p[i] = i; int cnt = 0; for(int i = edge_id; i < m; i++) { int e = r[i]; int x = find_p(u[e]), y = find_p(v[e]); if(x != y) { p[x] = y; cnt++; } if(cnt == n-1) return w[e]-w[r[edge_id]]; } return INF; } int main() { //freopen("input.txt", "r", stdin); while(cin>>n>>m && n) { for(int i = 0; i < m; i++) scanf("%d%d%d", &u[i], &v[i], &w[i]); for(int i = 0; i < m; i++) r[i] = i; sort(r, r+m, cmp); int ans = INF; for(int i = 0; i < m; i++) ans = min(ans, Kruscal(i)); if(ans == INF) ans = -1; cout << ans << endl; } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-26 02:59:34