poj 2349(最小生成树应用)

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

思路:由于有S个专门的通道,我们可以先求一次最小生成树,然后对于最小生成树上的边从大到小排序,前S-1条边用S-1个卫星通道连接,那么第S大条边就是我们要找的最小的D了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 #define MAXN 555
 8 #define inf 1LL<<60
 9 
10 struct Node{
11     int x,y;
12 }node[MAXN];
13 double map[MAXN][MAXN];
14 double lowcost[MAXN];
15 double dist[MAXN];
16 bool mark[MAXN];
17 int n,m;
18 
19 double Cal(int i,int j)
20 {
21     double d1=1.0*(node[i].x-node[j].x)*(node[i].x-node[j].x);
22     double d2=1.0*(node[i].y-node[j].y)*(node[i].y-node[j].y);
23     return sqrt(d1+d2);
24 }
25 
26 int cmp(const double &p,const double &q)
27 {
28     return p>q;
29 }
30 
31 double Prim(int u0)
32 {
33     int cnt=0;
34     memset(mark,false,sizeof(mark));
35     for(int i=1;i<=m;i++){
36         lowcost[i]=map[u0][i];
37     }
38     lowcost[u0]=0;
39     mark[u0]=true;
40     for(int i=1;i<m;i++){
41         double MIN=inf;
42         int v=u0;
43         for(int j=1;j<=m;j++){
44             if(!mark[j]&&lowcost[j]<MIN){
45                 MIN=lowcost[j],v=j;
46             }
47         }
48         if(MIN==inf)break;
49         mark[v]=true;
50         dist[cnt++]=lowcost[v];
51         for(int k=1;k<=m;k++){
52             if(!mark[k]&&map[v][k]<lowcost[k]){
53                 lowcost[k]=map[v][k];
54             }
55         }
56     }
57     sort(dist,dist+cnt,cmp);
58     //for(int i=0;i<cnt;i++)printf("%.2lf\n",dist[i]);
59     return dist[n-1];
60 }
61     
62         
63 int main()
64 {
65     int _case,a,b;
66     scanf("%d",&_case);
67     while(_case--){
68         scanf("%d%d",&n,&m);
69         for(int i=1;i<=m;i++)
70             for(int j=1;j<=m;j++)
71                 map[i][j]=map[j][i]=(i==j?0:inf);
72         for(int i=1;i<=m;i++){
73             scanf("%d%d",&node[i].x,&node[i].y);
74             for(int j=1;j<i;j++){
75                 map[i][j]=map[j][i]=Cal(i,j);
76             }
77         }
78         printf("%.2lf\n",Prim(1));
79     }
80     return 0;
81 }
82 
83 
84         
85             
86             
View Code

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值