poj2349-kruskal

题意:

n个站点,s个卫星系统,每个卫星系统只能安排在一个站点
有卫星系统的站点间通讯不需要代价
任意两点(i, j)间皆可通讯,代价为dis[i][j]
找到最小的代价使得任意两个站点间均可以通讯
n, s <= 1000

kruskal

1、把所有边按从小到大的顺序排序,遍历每条边(u,v)
2、u和v在同一个连通分量中,那么加入(u,v)会成环,不能选择。
3、如果u和v在不同的连通分量,那么(u,v)一定是最优的。 用反证法证。

#include <iostream>  
#include <cstdio>  //题意  注意 是除了删掉的点以外  最大的边
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 500005; //边的个数
int u[maxn], v[maxn];
double w[maxn], ans[maxn]; //分别代表第i条边的两个端点序号,和权值
int pr[maxn]; // 找父节点
int r[maxn]; //排序后第i小的边的序号保存在r[i]中
int s, p, m, k; //p个点 m条边

struct Pos
{
    int x, y;
}pos[maxn];
double getdis(int i, int j)
{
    return sqrt((pos[i].x-pos[j].x)*(pos[i].x-pos[j].x) + (pos[i].y-pos[j].y)*(pos[i].y-pos[j].y));
}
bool cmp(const int i, const int j)
{
    return (w[i] < w[j]);
}
int Find(int x)
{
    return pr[x] == x ? x : pr[x] = Find(pr[x]);
}

void kruskal()  // 如果u,v 在不同的连通分量,那么加入(u,v)一定是最优的
{
    for(int i=0; i<p; i++) //初始化并查集
        pr[i] = i;
    for(int i=0; i<m; i++) //初始化边序号
        r[i] = i;
    sort(r, r+m, cmp);
    k=0;
    for(int i=0; i<m; i++)
    {
        int e = r[i];
        int x = Find(u[e]); //当前边的端点所在的集合
        int y = Find(v[e]);
        if(x != y)
        {
            ans[k++] = w[e];
            pr[x] = y;
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&s,&p);
        m = 0;
        for(int i=0; i<p; i++)
        {
            scanf("%d%d",&pos[i].x, &pos[i].y);
        }
        for(int i=0; i<p-1; i++)
        {
            for(int j=i+1; j<p; j++)
            {
                u[m] = i;
                v[m] = j;
                w[m++] = getdis(i,j);
            }
        }
        kruskal();
        sort(ans, ans+k-1);

        printf("%.2f\n",ans[k-s]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值