题意:给出一个n(n<=100)结点的图,求苗条度(最大边减最小边的值)尽量小的生成树。
分析:枚举区间求最小生成树,不断更新ans
代码:
#include <map> #include <set> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <iomanip> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define ll long long #define mod 1000000007 #define mem(a) memset(a,0,sizeof(a)) using namespace std; const int maxn = 5000 + 5 , inf = 0x3f3f3f3f ; struct edge{ int v,e,w; bool operator < (const edge&temp)const{ return w<temp.w; } }; edge edges[maxn]; int fa[maxn]; int n,m,ans,cnt; void Init(){ for(int i = 1 ; i < maxn ; i ++) fa[i] = i; } int Find(int u){return fa[u]==u?u:fa[u]=Find(fa[u]);} void Kruskal(int L){ cnt=0; Init();int Max = -inf,Min=inf; for(int j= L ; j <= m ;j ++){ int v = edges[j].v; int e = edges[j].e; int w = edges[j].w; int x = Find(v); int y = Find(e); if(x!=y){ cnt++; fa[x] = y; Max = max(Max,w); Min = min(Min,w); if(cnt==n-1){ ans = min(ans,Max-Min); return; } } } } int main(){ // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){ ans = inf; for(int i = 1 ; i <= m ; i++) scanf("%d%d%d",&edges[i].v,&edges[i].e,&edges[i].w); sort(edges+1,edges+m+1); for(int i = 1 ; i <= m ; i ++){ Kruskal(i); } printf("%d\n",ans!=inf?ans:-1); } }