P1223 [小数据版]边权差值最小的生成树
这道题和最小生成树kruskal的代码几乎相同,只不过不一定是最小生成树,所以不一定从最短的边开始做生成树;所以将每一条边分别作为起点,然后枚举就行了......
#include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f inline int read() { int x = 0,ff = 1;char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') ff = -1; ch = getchar(); } while(isdigit(ch)) { x = (x<<1) + (x<<3) + (ch ^ 48); ch = getchar(); } return x * ff; } inline void write(int x) { if(x < 0) putchar('-'),x = -x; if(x > 9) write(x / 10); putchar(x % 10 + '0'); } struct node { int x,y,v; }e[100000]; int a,b,x,y,v,m = 0,fa[100000],mi = INF; inline bool cmp(node x,node y) { return x.v < y.v; } int get(int x) { return (x == fa[x]) ? x : (fa[x] = get(fa[x])); } int Kruskal(int ans) { int maxx = -1,minn = INF; for(int i = 1;i <= a;++i) fa[i] = i; int sum = 0,cnt = 0; sort(e + 1,e + m + 1,cmp); for(int i = ans;cnt < a - 1;++i) { ++sum; if(sum > m) return -1; // 所有的边都找过,不能构成树; int x = get(e[i % m].x),y = get(e[i % m].y); // i可能大于m,所以用i % m; if(x != y) { ++cnt; fa[x] = y; maxx = max(maxx,e[i % m].v); minn = min(minn,e[i % m].v); } } return maxx - minn; } int main() { a = read(); b = read(); for(int i = 1;i <= b;++i) { x = read(); y = read(); v = read(); e[++m].x = x; e[m].y = y; e[m].v = v; } for(int i = 1;i <= m;++i) mi = min(mi,Kruskal(i)); // 枚举不同的起点 write(mi); return 0; }