poj 2349 最小生成树

转载。。

题目链接:http://poj.org/problem?id=2349

这个问题是最小生成树的问题

假设已知,把所有铺设线路的村庄连接起来,构成一个图。需要卫星设备的台数就是图的连通支的个数。 

d越小,连通支就可能越多。 

那么,只需找到一个最小的d,使得连通支的个数小于等于卫星设备的数目。

把整个问题看做一个完全图,村庄就是点,图上两点之间的边的权值,就是两个村庄的直线距离。 

只需在该图上求最小生成树,d 的最小值即为第 K  长边! 

因为:最小生成树中的最长k-1条长边都去掉后,正好将原树分成了k 个连通分支,在每个连通分支上摆一个卫星设备即可 

那么剩下的各村庄之间的连线,最长不用超过 第k 长边的长度。

View Code
 1 #include<stdio.h>
2 #include<string.h>
3 #include<math.h>
4 #include<algorithm>
5 using namespace std;
6 #define M 1100
7 double map[M][M];
8 const double inf = 1e20;
9 bool flag[M];
10 double D[M];
11 struct point {
12 double x,y;
13 }P[M];
14 int tot;
15 int pre[M];
16 double ans[M];
17 double prime(int s,int n)
18 {
19 int i,v,k;
20 double mi;
21 double ret=0;
22 for(i=1;i<=n;i++){
23 flag[i]=0;
24 pre[i]=-1;
25 D[i]=inf;
26 }D[s]=0;flag[s]=1;v=s;
27 for(k=1;k<n;k++){
28 for(i=1;i<=n;i++)if(!flag[i]){
29 if(map[v][i]<D[i])
30 {
31 pre[i]=v;
32 D[i]=map[v][i];
33 }
34 }
35 mi=inf;v=-1;
36 for(i=1;i<=n;i++)
37 if(!flag[i]&&D[i]<mi)
38 mi=D[v=i];
39 if(pre[v]!=-1) ans[tot++]=map[pre[v]][v];
40 flag[v]=1;
41 ret+=mi;
42 }
43 return ret;
44 }
45 double dis(point a,point b)
46 {
47 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
48 }
49 int main()
50 {
51 int t,s,p,i,j;
52 scanf("%d",&t);
53 while(t--)
54 {
55 scanf("%d%d",&s,&p);
56 for(i=1;i<=p;i++)
57 scanf("%lf%lf",&P[i].x,&P[i].y);
58 for(i=1;i<=p;i++)
59 for(j=1;j<=p;j++)
60 map[i][j]=map[j][i]=dis(P[i],P[j]);
61 tot=0;
62 prime(1,p);
63 sort(ans,ans+p-1);
64 printf("%.2lf\n",ans[p-s-1]);
65 }
66 return 0;
67 }



posted @ 2011-11-05 18:05  Because Of You  Views(310)  Comments(0Edit  收藏  举报