POJ2349->最小生成树

该博客主要介绍了POJ2349题目,即如何在n个节点之间构建通信网络,确保通过卫星和线路连接所有节点,并求解所需的最长线路长度。博主指出这是一道关于最小生成树的问题,可以通过Prim或Kruskal算法来解决。通过Prim算法,可以记录最小生成树的所有边并排序,最长的边即为答案;而Kruskal算法则直接选择n-m条最短边得出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值