POJ2349->最小生成树
题意:
要在n个节点之间建立通信网络,其中m个节点可以用卫星直接连接,剩下的节点都要用线路连接,求剩下这些线路中最大的长度需要多长
题解:
明显还是最小生成树的题
如果用Prime算法,该算法现在V1集合中放入任意一个节点,然后每次选取和V1集合中的节点相连的最短的边的另一个节点加入到V1集合。
此时,可以把建成整棵最小生成树的所有边记录在一个数组里,然后排序,dist[n-m]就是答案如果是kruskal算法,该算法每次选取最短的边,只需选完n-m条边就能得到答案
Prime算法代码:
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <cmath>
#include <algorithm>
using namespace std ;
const double INF = 1000000000 ;
#define MAX 550
int n ,sum;
bool visit[MAX] ;
double cost[MAX][MAX] ;
double lowc[MAX] ;
double dist[MAX] ;
struct Node
{
double x, y ;
}MAP[MAX];
double Dis(Node a , Node b)
{
return sqrt((a.x - b.x)*(a.x - b.x) + (a.y-b.y)*(a.y-b.y)) ;
}
void init()
{
double temp ;
for(int i = 1 ; i <= n ; i ++) cost[i][i] = INF ;
for(int i = 1 ; i <= n ; i ++)
{
for(int j = i+1 ; j <= n ; j ++)
{
temp = Dis(MAP[i] , MAP[j]) ;
cost[i][j] = cost[j][i] = temp;
}
}
}
void Prime()
{
int cnt = 0 ;
memset(visit , false , sizeof(visit)) ;
visit[1] = true ;
for(int i = 1 ; i <= n ; i ++)
{
lowc[i] = cost[1][i] ;
}
lowc[1] = 0 ;
for(int i = 1 ; i < n ; i ++)
{
double minc = INF ;
int p = -1 ;
for(int j = 1 ; j <= n ; j ++)
{
if(!visit[j] && minc > lowc[j])
{
minc = lowc[j] ;
p = j ;
}
}
//if(minc == INF) break ;
visit[p] = true ;
dist[cnt ++] = minc ;
for(int j = 1 ; j <= n ; j ++)
{
if(lowc[j] > cost[p][j])
{
lowc[j] = cost[p][j] ;
}
}
}
sort(dist , dist + cnt) ;
printf("%.2f\n",dist[cnt - sum]) ;
}
int main()
{
int T ;
scanf("%d" , &T) ;
while(T --)
{
scanf("%d%d" ,&sum , &n) ;
for(int i = 1 ; i <= n ; i ++)
{
scanf("%lf%lf" , &MAP[i].x , &MAP[i].y) ;
}
init() ;
Prime() ;
}
return 0;
}