[水]Poj2349 Kruskal

原因:为了练习一下Kruskal,随便到poj找了一个求mst的题。- -

题意:给一堆城市的坐标点,任何两个城市之间有两种通讯方式,一种是直接卫星通讯,不管两个城市距离多远,都可以通讯,另一种是微波通讯,通讯距离不超过D,D越大成本越高,给出s个城市之间可以用卫星通讯,其他必须得用微波,求所有城市都可以互相通讯的最小成本。

分析:先用Kruskal求出mst,记录mst中的所有边,那么删除了最大的那s-1条边后最大的边就是答案,如果没有边了返回0,不过貌似这题不会所有城市之间都用卫星通讯。还有一个坑爹的地方就是输出时候的占位符必须是%0.2f,这个不能理解。。看了discuss改了才AC。

其他做法:直接二分答案然后验证。。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
typedef pair<int,int> P;
struct edge{   //无向边
   int u,v;
   double dis;
};
const int maxe = 2500005;
const int maxv = 505;
edge e[maxe];
P pot[maxv];
int V,E,s,res,fa[maxv],height[maxv];
bool cmp(edge a1,edge a2)
{
    return a1.dis<a2.dis;
}
void ini()
{
    for(int i=1;i<=V;i++)
    {
        fa[i]=i;
        height[i]=0;
    }
}
int findfa(int a)
{
    if(fa[a]==a) return a;
    return fa[a]=findfa(fa[a]);
}
bool same(int a,int b)
{
    return findfa(a)==findfa(b);
}
void unite(int a,int b)
{
    int faa=findfa(a),fab=findfa(b);
    if(height[faa]<height[fab])
        fa[faa]=fab;
    else
    {
        fa[fab]=faa;
        if(height[faa]==height[fab]) height[faa]++;
    }
}
double Kruscal()
{
    priority_queue<double> pq;
    sort(e+1,e+E+1,cmp);
    ini();
    for(int i=1;i<=E;i++)
    {
        edge nowe=e[i];
        if(!same(e[i].v,e[i].u))
        {
            unite(e[i].v,e[i].u);
            pq.push(e[i].dis);
        }
    }
    for(int i=1;i<s;i++)
    {
        pq.top();pq.pop();
    }
    if(pq.empty()) return 0;
    return pq.top();
}
double get_dis(P a,P b)
{
    return sqrt((a.first-b.first)*(a.first-b.first)+(a.second-b.second)*(a.second-b.second));
}
int main()
{
    //freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
      scanf("%d%d",&s,&V);  //已经有卫星通讯的城市数和点数
      for(int i=1;i<=V;i++)
        scanf("%d%d",&pot[i].first,&pot[i].second);
      int th=0;
      for(int i=1;i<=V;i++)
        for(int j=1;j<i;j++)
        {
           th++;
           e[th].u=i;e[th].v=j;e[th].dis=get_dis(pot[i],pot[j]);
        }
      E=th;
      printf("%0.2f\n",Kruscal()); //这里必须用%0.2f输出 不知道为什么
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值