题意:给出一副无向有权图,求生成树中最小的苗条度(最大权值减最小权值),如果不能生成树,就输出-1;
思路:将所有的边按权值有小到大排序,然后枚举每一条边,以这条边开始利用Kruskal算法生成树,生成过程中求出权值的最大值,这个最大值减去当前枚举的边的权值就是苗条度,再动态维护一下最小苗条度就可以了。
#include <iostream> #include <algorithm> #include <queue> #include <stack> #include <cstdio> #include <string> #include <cstring> #include <sstream> #include <cmath> #define INF 0x3f3f3f3f #define mod 1000000007; #define FRE() freopen("in.txt","r",stdin) using namespace std; const int maxn = 5005; struct edge { int st,en; int w; }e[maxn]; int pre[maxn]; int n,m; bool cmd(edge &a,edge &b) { return a.w < b.w; } int _Find(int x) { return x == pre[x] ? x : pre[x] = _Find(pre[x]); } int main() { //FRE(); while(scanf("%d%d",&n,&m) && n+m) { for(int i = 0; i < m; i++) { scanf("%d%d%d",&e[i].st,&e[i].en,&e[i].w); } sort(e, e+m, cmd); int ans = INF; for(int i = 0; i < m; i++)//从小到大枚举每一条边,之后用求得的最大值减去这条边的权值 { for(int i = 1; i <= n; i++) pre[i] = i; int cnt = n,mmax = -1; for(int j = i; j < m; j++) { int x = _Find(e[j].st),y = _Find(e[j].en); if(x != y) { pre[y] = x; cnt--; mmax = max(mmax, e[j].w);//求出最小生成树中最大的权值 } } if(cnt == 1)//因为是树,所以有n-1条边,当是一棵树的时候,就动态维护一下最小值 ans = min(ans, mmax - e[i].w); } if(ans == INF) printf("-1 "); else printf("%d ",ans); } return 0; }