题目链接:
http://poj.org/problem?id=2349
题目大意:
有n个警戒部队,现在要把这n个警戒部队编入一个通信网络,
有两种方式链接警戒部队:1,用卫星信道可以链接无穷远的部队.
2,用信号收发器可以链接周围d米以内的部队.
现在有s个卫星信道,问d最小是多少时能连接全部的警戒部队?
解题思路:
我是用求最小生成树,记录路径长度,对路径长度排序后,第k长的边就是答案,
但是队友是用最小k度限制生成树,因为我的方法它证明不了,也推翻不了~~~~,
最后我下去仔细想了想反证法还是可以证明的。
证明:
假设:先假设最小生成树的第k大边不是最优解。
证:现在有一MST,我从中删除了一条第k大的边s,则MST变成了两个联通分支,根据假设存在一条s'<s,可以使两个联通分支连起来变成联通树MST',因为s'<s,则MST'<MST,可得出假设不成立!!!!
1 #include <cmath> 2 #include <string> 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 using namespace std; 8 9 const int maxn = 500; 10 const int INF = 0x3f3f3f3f; 11 const double Exp = 1e-10; 12 13 struct point 14 { 15 int x, y; 16 int length(point a) 17 { 18 return (a.x - x)*(a.x - x) + (a.y - y)*(a.y - y); 19 } 20 }; 21 22 int cost[maxn+10][maxn+10], lowc[maxn+10]; 23 int vis[maxn+10], num[maxn+10]; 24 25 void init () 26 { 27 for (int i=0; i<maxn+10; i++) 28 for (int j=0; j<maxn; j++) 29 cost[i][j] = INF; 30 } 31 int prim (int n) 32 { 33 int i, j; 34 memset (vis, 0, sizeof(vis)); 35 vis[0] = 1; 36 for (i=0; i<n; i++) 37 lowc[i] = cost[0][i]; 38 for (i=1; i<n; i++) 39 { 40 int p, mini = INF; 41 for (j=0; j<n; j++) 42 if (!vis[j] && lowc[j] < mini) 43 { 44 p = j; 45 mini = lowc[j]; 46 } 47 vis[p] = 1; 48 for (j=0; j<n; j++) 49 { 50 if (!vis[j]) 51 lowc[j] = min(lowc[j], cost[p][j]); 52 } 53 } 54 } 55 56 int main () 57 { 58 int n, s, p; 59 point P[maxn + 10]; 60 scanf ("%d", &n); 61 while (n --) 62 { 63 scanf ("%d %d", &s, &p); 64 for (int i=0; i<p; i++) 65 { 66 scanf ("%d %d", &P[i].x, &P[i].y); 67 for (int j=0; j<i; j++) 68 cost[i][j] = cost[j][i] = P[i].length(P[j]); 69 } 70 prim (p); 71 sort (lowc, lowc+p, greater<int>()); 72 printf ("%.2f\n", sqrt(lowc[s-1])); 73 } 74 return 0; 75 }