题意:给你一个无向图,没有重边,没有自环,要你求该图中一颗生成树,但是这个生成树的最大边与最小边的差值要最小。
如果固定一个最小边,求得最小生成树后,最大边也就知道了,其实这个也意味着在固定最小边的情况下最小生成树的最大边是固定的,可是为什么我们一定要求最小生成树呢,因为其他的生成树的最大边与最小边的差值要大于等于最小生成树的大小边之差,这个的原因大家可以自己仔细想想最小生成树的性质和次小生成树的求法(枚举每条最小生成树上的边,不要此条边求得的生成树,选最小一个就是了,这个就意味着次小生成树里面肯定有一条边要比最小生成树的大,其它的相同)。这样说来的话,我们只需将边排好序后,枚举每条边,并用Krustral求得最小生成树就可以了……(参考:http://blog.csdn.net/sdj222555/article/details/7698978)
View Code
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 struct node 8 { 9 int x,y; 10 int w; 11 }edge[10000]; 12 int father[110]; 13 int n,m; 14 15 bool cmp(const node& a,const node& b) 16 { 17 return a.w < b.w; 18 } 19 20 int find(int x) 21 { 22 return father[x] = (x == father[x]?x:(find(father[x]))); 23 } 24 25 int Krustral(int x) 26 { 27 int num = 0; 28 int ans = -1; 29 for(int i = x;i < m;i ++) 30 { 31 int fa = find(edge[i].x); 32 int fb = find(edge[i].y); 33 if(fa == fb) 34 { 35 continue; 36 } 37 father[fa] = fb; 38 num ++; 39 if(num == n-1) 40 { 41 ans = edge[i].w; 42 break; 43 } 44 } 45 return ans; 46 } 47 48 int main() 49 { 50 //freopen("in.txt","r",stdin); 51 // freopen("out.txt","w",stdout); 52 while(cin >> n >> m,n||m) 53 { 54 for(int i = 0;i < m;i ++) 55 { 56 cin >> edge[i].x >> edge[i].y >> edge[i].w; 57 } 58 if(m < n - 1) 59 { 60 cout << "-1" << endl; 61 continue; 62 } 63 sort(edge,edge+m,cmp); 64 int minn = -1; 65 for(int i = 0;i <= m - n + 1;i ++) 66 { 67 for(int j = 1;j <= n;j ++) 68 { 69 father[j] = j; 70 } 71 int ans = Krustral(i); 72 if(ans != -1) 73 { 74 if(minn == -1 || minn > ans - edge[i].w) 75 { 76 minn = ans - edge[i].w; 77 } 78 } 79 } 80 cout << minn << endl; 81 } 82 return 0; 83 }