poj2349最小生成树prim算法
题目:
有s个satellite channels,但有p(p>s)个地方,若任意两个地方有
satellite channels,则无视该距离,并且剩余的地方只能与其他地方
通过无线电连接,需要距离,且需要的距离只与最大距离有关,问该最大
距离的最小值(大概是这样啦)
分析:
实际上就是求最小生成树中的第p-s大的数,可以先通过prim算法生成
最小生成树,然后通过对生成树中的边进行快速排序,得到第p-s大的数
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
#define X 1100
#define INF 10005
int x[X],y[X];
double dis[X][X],dp[X],q[X];
bool use[X];
int cmp(double a,double b)
{ //sort内部比较函数
return a<b;
}
int main()
{
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
int t,s,p;
double a,b;
cin>>t;
while(t--)
{
cin>>s>>p;
for(int i=0;i<p;i++)
scanf("%d%d",&x[i],&y[i]);
//求距离,因为任意不同两个地方均可连接
for(int i=0;i<p-1;i++)
for(int j=0;j<p;j++)
{
a = x[i]-x[j];
b = y[i]-y[j];
dis[i][j] = dis[j][i] = sqrt(a*a+b*b);
}
////////////////以下是prim算法模板
memset(use,false,sizeof(use));
memset(dp,INF,sizeof(dp));
for(int i=0;i<p;i++)
dp[i] = dis[0][i];
use[0] = true;
double MIN;
int k,cnt = 0;
for(int i=0;i<p-1;i++)
{
MIN = INF;
for(int j=1;j<p;j++)
if(!use[j]&&MIN>dp[j])
{
MIN = dp[j];
k = j;
}
q[cnt++]=MIN;//通过数组q[]储存最小生成树中的边长
use[k] = true;
for(int j=1;j<p;j++)
if(!use[j])
dp[j]=min(dp[j],dis[k][j]);
}
sort(q,q+cnt,cmp);//对边长进行排序
printf("%.2lf\n",q[p-s-1]);
}
return 0;
}