题目链接: 传送门
给出一个n(2 <= n <= 100)个结点的无向图,找一颗苗条度(最大边减最小边)最小的生成树。图中不包含自环和重边。
解题思路:
枚举树上的最小边,从这条最小边开始构建MST,此时这棵树是以该边为最小边的苗条度最小的生成树。因为构建MST时会使最大边最小。
代码:
#include <iostream> #include <stack> #include <vector> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef long long llt; const int N = 110; const int M = 510; const int INF = 0x3fffffff; const int mod = 10000; struct Edge{ int u,v,w; bool operator < (const Edge&a) const{ return a.w > w; } }edge[N*N]; int parent[N]; int n,m; void init() { for(int i = 0; i < N; ++i) parent[i] = i; } int find(int a) { while(a != parent[a]){ parent[a] = parent[parent[a]]; a = parent[a]; } return a; } void merge(int a,int b) { int i = find(a); int j = find(b); if(i != j) parent[i] = j; } int kruskal(int k) { int cnt = 0; for(int i = k; i < m; ++i){ int u = edge[i].u; int v = edge[i].v; if(find(u) != find(v)){ cnt++; merge(u,v); } if(cnt == n-1){ return edge[i].w; } } return -1; } int main() { while(~scanf("%d%d",&n,&m)){ if(n == 0 && m == 0) break; for(int i = 0; i < m; ++i){ scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); } sort(edge,edge+m); init(); int ans = kruskal(0); if(ans == -1){ printf("-1\n"); continue; } ans -= edge[0].w; for(int i = 1; i <= m-n+1; ++i){ init(); int r = kruskal(i); if(r == -1) continue; ans = min(ans,r-edge[i].w); } printf("%d\n",ans); } // system("PAUSE"); return 0; }