- 题目大意
给出N个点,M条边,求出一棵包含N个点的树,且树的最大权值-最小权值达到最小。
- 解题思路
我们可以先把边排序,枚举最小的,然后利用kruskal加边,当图第一次连通的时候当前的边就是尽可能小的最大边,更新答案即可。
- 代码
#include<algorithm> #include<cstdio> #include<cmath> using namespace std; const int MAX = 1e6; const int INF = 0x3f3f3f; int fa[MAX]; int sum,sum1,tmp; void init(int n) { for (int i = 1; i <= n; i++) { fa[i] = i; } } struct Edge { int u, v, w; bool operator<(const Edge &rhs)const { return w < rhs.w; } }e[MAX]; int find(int x) { if (x == fa[x]) return x; else return fa[x] = find(fa[x]); } bool Union(int x, int y) { int fx = find(x), fy = find(y); if (fx == fy) return false; fa[fx] = fy; return true; } void kruskal(int n,int m) { sort(e, e + m); for (int j = 0; j < m; j++) { init(n); sum = 0; int minn = INF, maxn = -INF; for (int i = j; i < m; i++) { int u = e[i].u, v = e[i].v, w = e[i].w; if (Union(u, v)) { sum ++; maxn = max(maxn, w); minn = min(minn, w); if (sum == n - 1) { tmp = min(tmp, (maxn - minn)); break; } } } } } int main() { int n, m; while (scanf("%d%d", &n, &m)) { if (n == 0 && m == 0) break; tmp=INF; for (int i = 0; i<m; i++) { scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w); } kruskal(n,m); if (tmp==INF) printf("-1\n"); else printf("%d\n", tmp); } return 0; }