b_lg_无线通讯网 & 北极通讯网络(问题转化+kruskal)
无线通讯网
每个边防哨所都要配备无线电收发器;有一些哨所还可以增配卫星电话(无线电话的通信距离为无限长)。
每一对哨所之间的通话距离都是同一个D,给定n个哨站和m个收发器,
你的任务是确定收发器必须的最小通话距离D,使得每一对哨所之间至少有一条通话路径(直接的或者间接的)
思路
贪心:n个无线电安排在边权最大的点上;然后让剩下的m-n个哨站安装收发器;
kruskal取前m-n(m-1-(s-1),m-1条减去无线电话省去的s-1条)条边中的最大者(因为要保证m-n条边中任意两条满足两点通信)
#include<bits/stdc++.h>
using namespace std;
const int N=505;
int n,m,fa[N];
struct node {
double x,y,w;
}a[N*N], e[N*N];
int find(int u) {
return fa[u]==u ? u : fa[u]=find(fa[u]);
}
double getDist(node& a, node& b) {
return sqrt(((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)));
}
int main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin>>n>>m; for (int i=0; i<m; i++) cin>>a[i].x>>a[i].y, fa[i]=i;
int c=0;
for (int i=0; i<m; i++)
for (int j=0; j<i; j++) {
e[c].x=i, e[c].y=j, e[c++].w=getDist(a[i], a[j]);
}
sort(e, e+c, [&](node a, node b) {return a.w<b.w;});
double ans=0x3f3f3f3f;
for (int i=0, t=m-n; i<c && t; i++) {
int fx=find(e[i].x), fy=find(e[i].y);
if (fx!=fy) {
fa[fx]=fy;
ans=e[i].w, t--;
}
}
printf("%.2lf", ans);
return 0;
}
北极通讯网络
共有n座村庄,k台卫星设备,无线电收发机有一个不同的参数d,d越大价格越贵,计算出应该如何分配这 k 台卫星设备,才能使所拥有的无线电收发机的d值最小
思路:一开始有n个连通块,肯定是将边权最小的村庄用收发器连接,最后用k个卫星设备将k个连通块连接起来
#include<bits/stdc++.h>
using namespace std;
const int N=505;
int n,k,m,fa[N];
struct edge {
int u,v;
double w;
}E[N*N];
struct node {
int x,y;
}A[N];
double getDist(node& a, node& b) {
int dx=a.x-b.x, dy=a.y-b.y;
return sqrt(dx*dx+dy*dy);
}
int find(int u) {return fa[u]==u ? u : fa[u]=find(fa[u]);}
double kruskal() {
for (int i=0; i<n; i++) fa[i]=i;
sort(E,E+m,[&](edge a, edge b) {return a.w<b.w;});
double d=0;
int c=n;
for (int i=0; i<m && c>k; i++) {
int fu=find(E[i].u), fv=find(E[i].v);
if (fu!=fv) {
fa[fu]=fv, d=E[i].w;
c--;
}
}
return d;
}
int main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin>>n>>k;
for (int i=0; i<n; i++) cin>>A[i].x>>A[i].y;
for (int i=0; i<n; i++)
for (int j=0; j<i; j++) {
E[m++]={i,j,getDist(A[i], A[j])};
}
printf("%.2lf", kruskal());
return 0;
}