Light OJ 1029- Civil and Evil Engineer (图论-最小生成树)
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1029
题目大意:一个发电站,给n座房子供电, 任意房子之间有电线直接或者间接相连接, 现在想知道需要连接这些房子花费的平均电线长度。平均电线长度 = (最长电线长度 + 最短电线长度)/ 2;
解题思路:裸的最小生成树
代码如下:
#include <bits/stdc++.h> using namespace std; const int N = 1003; struct edge { int s, t, l; edge() {} edge(int s, int t, int l):s(s), t(t), l(l) {} }; vector<edge>vec; int par[N], Rank[N]; int n; void init() { for(int i=0; i<=n; ++ i) par[i] = i, Rank[i] = 0; } int Find(int x) { if(par[x] == x) return x; else return par[x] = Find(par[x]); } void unite(int x, int y) { x = Find(x), y = Find(y); if(x == y) return ; if(Rank[x] < Rank[y]) par[x] = y; else { par[y] = x; if(Rank[x] == Rank[y]) Rank[x] ++; } } bool same(int x, int y) { return Find(x) == Find(y); } bool cmp(const edge &a, const edge &b) { return a.l < b.l; } bool Cmp(const edge &a, const edge &b) { return a.l > b.l; } int kruskal(int m) { init(); if(m == 1) sort(vec.begin(), vec.end(), cmp); else sort(vec.begin(), vec.end(), Cmp); int res = 0; for(int i=0; i<vec.size(); ++ i) { edge e = vec[i]; if(!same(e.s, e.t)) { unite(e.s, e.t); res += e.l; } } return res; } void solve(int cases) { scanf("%d", &n); vec.clear(); while(1) { int s, t, l; scanf("%d%d%d", &s, &t, &l); if((s || t || l) == false) break; vec.push_back(edge(s, t, l)); } int ans = 0; ans += kruskal(1); ans += kruskal(2); if(ans & 1) printf("Case %d: %d/%d\n", cases, ans, 2); else printf("Case %d: %d\n", cases, ans/2); } int main() { int t; scanf("%d", &t); for(int i=1; i<=t; ++ i) solve(i); return 0; }