思路:枚举所有可能的情况。
枚举最小边, 然后不断加边, 直到联通后, 这个时候有一个生成树。这个时候,在目前这个最小边的情况可以不往后枚举了,
可以直接更新答案后break。
因为题目求最大边减最小边最小, 在最小边确定的情况下, 要使得差值最小, 就要使得最大边最小, 那么排序之后加边后
的第一个生成树一定是此情况下的最优解, 因为这个时候最大边最小, 后面的边肯定更大。
细节(1)注意题目给的点标号从1开始还是从0开始。(2)边数组可以用vector(3)find函数最后 return f[x]。
#include<cstdio>
#include<vector>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;
const int MAXN = 112;
struct node
{
int w, u, v;
node(int u = 0, int v = 0, int w = 0) : u(u), v(v), w(w) {}
bool operator < (const node& rhs) const
{
return w < rhs.w;
}
};
vector<node> Edge;
int f[MAXN], n, m;
int find(int x)
{
if(f[x] != x)
f[x] = find(f[x]);
return f[x];
}
int main()
{
while(~scanf("%d%d", &n, &m) && n)
{
Edge.clear();
REP(i, 0, m)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
Edge.push_back(node(u, v, w));
}
sort(Edge.begin(), Edge.end());
int ans = 1e9;
REP(L, 0, m)
{
int sum = 0;
REP(i, 1, n + 1) f[i] = i;
REP(R, L, m)
{
int u = find(Edge[R].u), v = find(Edge[R].v);
if(u != v)
{
f[u] = v;
if(++sum == n - 1)
{
ans = min(ans, Edge[R].w - Edge[L].w);
break;
}
}
}
}
printf("%d\n", ans == 1e9 ? -1 : ans);
}
return 0;
}