求一颗生成树,让最大边最小边差值最小
我们利用克鲁斯卡尔的规律来思考一下。
克鲁斯卡尔算法是先对边进行排序,每次都是从最小的到最大的找。
我们要找差值最小的,那么枚举最小边。之后最枚举的最小边开始往后找,建立一颗生成树。
比较差值,输出最小的即可。
- #include <iostream>
- #include <map>
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #define MAXN 105
- #define MAXM 10005
- #define INF 1000000000
- using namespace std;
- int n, m;
- int father[MAXN];
- struct Edge
- {
- int x, y, w;
- bool operator <(const Edge &a) const{
- return w < a.w;
- }
- }edge[MAXM];
- int find(int x)
- {
- if(father[x] == x) return x;
- int t = find(father[x]);
- father[x] = t;
- return t;
- }
- int main()
- {
- while(scanf("%d%d", &n, &m) != EOF)
- {
- if(n == 0 && m == 0) break;
- for(int i = 0; i < m; i++)
- scanf("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].w);
- sort(edge, edge + m);
- int ans = INF;
- for(int i = 0; i <= m - n + 1; i++)
- {
- int tmp = -1, sum = 0;
- for(int j = 1; j <= n; j++) father[j] = j;
- for(int j = i; j < m; j++)
- {
- int fx = find(edge[j].x), fy = find(edge[j].y);
- if(fx != fy)
- {
- sum ++;
- father[fx] = fy;
- if(sum == n - 1)
- {
- tmp = edge[j].w - edge[i].w;
- break;
- }
- }
- }
- if(tmp != -1 && tmp < ans) ans = tmp;
- }
- if(ans < INF) printf("%d\n", ans);
- else printf("-1\n");
- }
- return 0;
- }