給出N個點,M條邊,求出一棵包含N個點的樹,且樹的最大權值-最小權值達到最小。spa
咱們能夠先把邊排序,枚舉最小的,而後利用kruskal加邊,當圖第一次連通的時候當前的邊就是儘量小的最大邊,更新答案便可。blog
#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; }