Description
Any two outposts with a satellite channel can communicate via the satellite, regardless of their location. Otherwise, two outposts can communicate by radio only if the distance between them does not exceed D, which depends of the power of the transceivers. Higher power yields higher D but costs more. Due to purchasing and maintenance considerations, the transceivers at the outposts must be identical; that is, the value of D is the same for every pair of outposts.
Your job is to determine the minimum D required for the transceivers. There must be at least one communication path (direct or indirect) between every pair of outposts.
Input
Output
Sample Input
1 2 4 0 100 0 300 0 600 150 750
Sample Output
212.13
大致題意:有n個衛星和m個哨所,現在要把m個哨所併入通信網絡,在n個哨所中安放衛星,安放有衛星的哨所互相通信可以無視距離,剩下的哨所需要配置信號接收器,信號接收器接收信號的半徑越大價格越高。每個哨所安放的信號接收器的型號都一樣,即信號接收半徑都一樣,求最低要購買接收信號半徑爲多少的信號接收器.
解題思路:用最小生成樹解,用最小生成樹求出聯通所有哨所的所有路徑長度,然後在裏面最長的路徑所聯通的哨所
裏放衛星。
1.普里姆算法:
#include <iostream> // 普里姆算法
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define sc(a) scanf("%d",&a)
#define nsc(a,b) scanf("%d %d",&a,&b)
#define pr(a) printf("%d\n",a)
#define mem(a,x) memset(a,x,sizeof(a))
#define lf(i,l,r) for(int i=l;i<r;i++)
#define inf 0x3f3f3f3f
#define N 510
int t,n,m,cnt,x[N],y[N],vis[N];
double spot[N][N],num[N],dis[N];
void solve()
{
int tol;
cnt=0;
lf(i,1,m+1)
dis[i]=spot[1][i];
vis[1]=1;
lf(i,1,m)
{
tol=-1;
num[cnt]=inf; //用num數組來存儲最短路徑中的所有路徑。
lf(j,1,m+1)
{
if(!vis[j]&&num[cnt]>dis[j])
{
num[cnt]=dis[j];
tol=j;
}
}
cnt++;
if(tol==-1)
return ;
vis[tol]=1;
lf(j,1,m+1)
if(!vis[j])
dis[j]=min(dis[j],spot[tol][j]);
}
return ;
}
int main()
{
sc(t);
while(t--)
{
nsc(n,m);
lf(i,1,m+1)
{
vis[i]=0;
nsc(x[i],y[i]);
spot[i][i]=inf;
lf(j,1,i)
{
spot[i][j]=spot[j][i]=sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
}
solve();
sort(num,num+cnt); //排序,因爲衛星要放在裏面最長路徑連接的哨所
printf("%.2lf\n",num[cnt-n]); // 一共cnt-1條路徑,n-1條路徑可以通過放衛星替換
}
return 0;
}
2.克魯斯卡爾算法:
#include <iostream> // 克魯斯卡爾算法
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define sc(a) scanf("%d",&a)
#define nsc(a,b) scanf("%d %d",&a,&b)
#define pr(a) printf("%d\n",a)
#define mem(a,x) memset(a,x,sizeof(a))
#define lf(i,l,r) for(int i=l;i<r;i++)
#define inf 0x3f3f3f3f
#define N 510
int t,n,m,cnt,x[N],y[N],p[N];
double num;
struct node
{
int s;
int e;
double v;
} spot[N*N>>1];
int Find(int x)
{
if(x!=p[x])
{
p[x]=Find(p[x]);
}
return p[x];
}
int cmp(node a,node b)
{
return a.v<b.v;
}
void solve()
{
int tol=0;
num=0;
lf(i,1,cnt)
{
int xx=Find(spot[i].s);
int yy=Find(spot[i].e);
if(xx!=yy)
{
p[xx]=yy;
tol++; //tol代表找到的是第幾條小的邊
if(tol==m-n) //第m-n條邊就是沒有替換的最後的一條邊。
{
num=spot[i].v;
return ;
}
}
}
return ;
}
int main()
{
sc(t);
while(t--)
{
cnt=1;
nsc(n,m);
lf(i,1,m+1)
{
p[i]=i;
nsc(x[i],y[i]);
lf(j,1,i)
{
spot[cnt].s=i;
spot[cnt].e=j;
spot[cnt++].v=sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
}
sort(spot+1,spot+cnt,cmp); //先排序。
solve();
printf("%.2lf\n",num);
}
return 0;
}