题目
The Department of National Defence (DND) wishes to connect several northern outposts by a wireless network. Two different communication technologies are to be used in establishing the network: every outpost will have a radio transceiver and some outposts will in addition have a satellite channel.
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
Your job is to determine the minimum
Input
The first line of input contains
N
, the number of test cases. The first line of each test case contains
Output
For each case, output should consist of a single line giving the minimum D required to connect the network. Output should be specified to 2 decimal points.
Sample Input
1
2 4
0 100
0 300
0 600
150 750
Sample Output
212.13
题意
有
1、任意两个站点都可以联系(直接或者间接);
2、使任意两站点的最大通信花费变得最小。
需要输出最大的通信花费。
思路
最小生成树的问题,利用
有两种情况:1、
u
和
2、如果
u
,
现在需要知道三件事:
1、在一张全联通图的最小生成树中,新增一条权为0的边,新增加的边则取代形成的环中的另外一条边形成新的最小生成树。
2、在一张全连通图中,若在其最小生成树中挑选
S
个节点,在其两两间添加权为
3、在一张全连通图中,新增的一条边可以和任意一条边构成环。
于是,利用
Kruskal
算法在求最小生成树的时候,如果
u
和
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<cmath>
#include<set>
#include<map>
#include<cstdlib>
#include<functional>
#include<climits>
#include<cctype>
#include<iomanip>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
#define INF 0x3f3f3f3f
#define mod 1e9+7
#define clr(a,x) memset(a,x,sizeof(a))
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
const double eps = 1e-6;
int fa[250005];
vector<double> ans;
void init(int n)
{
for(int i=0;i<=n;i++)
{
fa[i]=i;
}
}
int find(int x)
{
if(fa[x]!=x)
fa[x]=find(fa[x]);
return fa[x];
}
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return ;
else
fa[x]=y;
}
bool same(int x,int y)
{
return find(x)==find(y);
}
vector <pair<double,PII> > G;
void add_egde(int u,int v,double d)
{
G.pb(mp(d,mp(u,v)));
}
void Kruskal(int n)
{
init(n);
sort(G.begin(),G.end());
int m=G.size();
int num=0;
for(int i=0;i<m;i++)
{
pair<double,PII> p=G[i];
int x=p.second.first;
int y=p.second.second;
double d=p.first;
if(!same(x,y))
{
unite(x,y);
num++;
ans.pb(d); //将边权放入vector中
}
if(num==n-1)
break;
}
}
double dis(double x1,double y1,double x2,double y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
void joint(int x,int y)
{
x=find(x);
y=find(y);
if(x!=y)
{
fa[x]=y;
}
}
int main()
{
int t;
cin>>t;
int s,p;
while(t--)
{
pair<double,double> P[505];
G.clear();
ans.clear();
cin>>s>>p;
for(int i=0;i<p;i++)
{
cin>>P[i].first>>P[i].second;
}
for(int i=0;i<p;i++)
for(int j=i+1;j<p;j++)
{
double d=dis(P[i].first,P[i].second,P[j].first,P[j].second);
add_egde(i,j,d);
add_egde(j,i,d);
}
Kruskal(p);
printf("%.2f\n",ans[p-s-1]);
}
return 0;
}
总结
自己理解好久以及在大佬的帮助下最终还是做出了,太菜了。。。