UVa10369 Arctic Network

基本方法网上有, 这里给出证明.

网上的证明基本都是瓶颈生成树, 但是并不能说明

" 任意生成树的第 i 大边不小于最小生成树的第 i 大边 "

证明:

考虑做Kruska

那么一条权值为v的边小于最小生成树里的第k条边

当且仅当只考虑权值小于等于v的边时图上连通块个数大于n-k

那么如果v是某个生成树的第k小边

那小于等于v的边至多把图连成n-k个连通块

(我是说连通块个数小于等于n-k

所以v不可能小于最小生成树的第k小边

(感谢@_rqy)

证毕.

证明了这个结论, 代码就很好写了.

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <cmath>
 7 using namespace std;
 8 typedef pair<int, int> P;
 9 const int MAXN = 500 + 10;
10 
11 struct _edge
12 {
13     int from, to; double cost;
14     bool operator <(const _edge &rhs) const{
15         return cost < rhs.cost;
16     }
17 };
18 
19 vector<_edge> E;
20 P pos[MAXN];
21 int N, p, S;
22 
23 inline double calcdis(P x, P y)
24 {return sqrt(pow(fabs(x.first - y.first), 2) + pow(fabs(x.second - y.second), 2));}
25 
26 namespace ufs
27 {
28     int fa[MAXN];
29     inline void init(){for(int i = 1; i <= p; i++) fa[i] = i;}
30     int findfa(int x) {return fa[x] == x ? x : findfa(fa[x]);}
31     inline void unite(int x, int y) {fa[findfa(x)] = findfa(y);}
32 }
33 
34 vector<double> ans; 
35 void solve()
36 {
37     E.clear();
38     for(int i = 1; i <= p; i++)
39         for(int j = i + 1; j <= p; j++)
40             E.push_back((_edge){i, j, calcdis(pos[i], pos[j])});
41     sort(E.begin(), E.end());
42 
43     using namespace ufs;
44 
45     init(); ans.clear(); int cnt = 0;
46     for(int i = 0, u, v; i < (int) E.size(); i++)
47     {
48         u = findfa(E[i].from), v = findfa(E[i].to);
49         if(u == v) continue;
50         unite(u, v); cnt++;
51         ans.push_back(E[i].cost);
52         if(cnt == p - 1) break;
53     }
54     printf("%.2lf
", ans[ans.size() - S]);
55 }
56 
57 int main()
58 {
59     //freopen("10369.in", "r", stdin);
60     //freopen("10369.out", "w", stdout);
61     cin>>N;
62     while(N--)
63     {
64         cin>>S>>p;
65         for(int i = 1, x, y; i <= p; i++)
66         {
67             scanf("%d%d", &x, &y);
68             pos[i] = P(x, y);
69         }
70         solve();
71     }
72     return 0;
73 }

第N次把kruskal的

u = findfa(E[i].from), v = findfa(E[i].to);

 写成

u = E[i].from, v = E[i].to;

 , 气啊.

原文地址:https://www.cnblogs.com/wsmrxc/p/9225364.html