题目链接:

https://vjudge.net/problem/POJ-2349

题目大意:

要在n个节点之间建立通信网络,其中m个节点可以用卫星直接连接,剩下的节点都要用线路连接,求剩下这些线路中最大的长度需要多长

思路:

还是MST的裸题,由于有m个节点可以用卫星连接,所以求出MST后,最长的m-1条边都可以用卫星连接,只需要求出第m长的边即可,直接用prim算法,保存mst每条边的长度,排序后直接输出第m长的边。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<sstream>
using namespace std;
typedef long long ll;
typedef pair<int, int> Pair;
const int maxn = 1e3 + ;
const int INF = << ;
int dir[][] = {,,,,-,,,-};
int T, n, m;
double Map[maxn][maxn];//存图
double lowcost[maxn], ans[maxn];
int mst[maxn], tot;
Pair a[maxn];
void prim(int u)//最小生成树起点
{
for(int i = ; i <= n; i++)//初始化两个数组
{
lowcost[i] = Map[u][i];
mst[i] = u;
}
mst[u] = -;//设置成-1表示已经加入mst
for(int i = ; i <= n; i++)
{
double minn = INF;
int v = -;
//在lowcost数组中寻找未加入mst的最小值
for(int j = ; j <= n; j++)
{
if(mst[j] != - && lowcost[j] < minn)
{
v = j;
minn = lowcost[j];
}
}
if(v != -)//v=-1表示未找到最小的边,
{//v表示当前距离mst最短的点
//printf("%d %d %d\n", mst[v], v, lowcost[v]);//输出路径
ans[tot++] = lowcost[v];
mst[v] = -;
for(int j = ; j <= n; j++)//更新最短边
{
if(mst[j] != - && lowcost[j] > Map[v][j])
{
lowcost[j] = Map[v][j];
mst[j] = v;
}
}
}
}
//printf("weight of mst is %d\n", sum_mst);
sort(ans, ans + tot);
printf("%.2f\n", ans[n - m - ]);//输出第m长的边
}
int main()
{
cin >> T;
while(T--)
{
cin >> m >> n;
for(int i = ; i <= n; i++)cin >> a[i].first >> a[i].second;
for(int i = ; i <= n; i++)
{
for(int j = ; j <= n; j++)
Map[i][j] = Map[j][i] = sqrt((a[i].first - a[j].first) * (a[i].first - a[j].first) + (a[i].second - a[j].second) * (a[i].second - a[j].second));
}
tot = ;
prim();
}
return ;
}
05-11 13:12