UVa 1395 (最小生成树) Slim Span
题意:
规定一棵生成树的苗条度为:最大权值与最小权值之差。给出一个n个顶点m条边的图,求苗条度最小的生成树。
分析:
按照边的权值排序,枚举边集的连续区间[L, R]的左边界L,如果这些区间刚好满足一个生成树,则存在一个苗条度不超过W[R] - W[L]的生成树。
话说,代码中用了STL的vector,慢了很多。
1 #include <cstdio> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 6 const int INF = 1000000000; 7 const int maxn = 100 + 10; 8 int pa[maxn]; 9 10 int findset(int x) { return x == pa[x] ? x : pa[x] = findset(pa[x]); } 11 12 struct Edge 13 { 14 int u, v, w; 15 Edge(int u, int v, int w):u(u), v(v), w(w) {} 16 bool operator < (const Edge& rhs) const 17 { 18 return w < rhs.w; 19 } 20 }; 21 22 vector<Edge> G; 23 24 int main() 25 { 26 //freopen("in.txt", "r", stdin); 27 int n, m; 28 while(scanf("%d%d", &n, &m) == 2 && n) 29 { 30 G.clear(); 31 int u, v, w; 32 for(int i = 0; i < m; ++i) 33 { 34 scanf("%d%d%d", &u, &v, &w); 35 G.push_back(Edge(u, v, w)); 36 } 37 sort(G.begin(), G.end()); 38 int ans = INF; 39 for(int L = 0; L <= m - n + 1; ++L) 40 { 41 for(int i = 1; i <= n; ++i) pa[i] = i; 42 int cnt = n; 43 for(int R = L; R < m; ++R) 44 { 45 int u = findset(G[R].u), v = findset(G[R].v); 46 if(u != v) 47 { 48 pa[u] = v; 49 if(--cnt == 1) { ans = min(ans, G[R].w - G[L].w); } 50 } 51 } 52 } 53 if(ans == INF) ans = -1; 54 55 printf("%d\n", ans); 56 } 57 58 return 0; 59 }