P4047 [JSOI2010]部落划分

Posted 人生有味是清欢

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4047 [JSOI2010]部落划分相关的知识,希望对你有一定的参考价值。

算法

最小生成树

思路

我们把每个点看成一个部落,每次取最小距离的两个抱团,同时部落也减少了一个....然后减减减,直到部落数==目标数,此时下一个不同部落的距离就是最短的距离!

代码

 

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath> 
const int MA = 1e7;
using namespace std;
int o,n,k,num,flag;
int fa[MA];
inline int read()
{
    int x = 0;
    char c = getchar();
    while (!isdigit(c))c = getchar();
    while(c>=‘0‘&&c<=‘9‘)
    {
        x = x*10+c-‘0‘;
        c = getchar();
    }
    return x;
}
struct s
{
    int x,y;double l; 
}ass[MA],e[MA];//结构体存点; 

double cmp(s x,s y)
{   return x.l < y.l;}
//比较边长;
//
int find(int a)
{
    if(fa[a]!=a)
        fa[a] = find(fa[a]);
    return fa[a];
}
void unionn(int a,int b)
{   fa[find(b)] = find(a); }
//并查集;
void kruskal()
{
    for(int i=1;i<=o;i++)
    {
        if(num==n-k) flag = 1;
        if(find(e[i].x)!=find(e[i].y))
        {
            num++;
            unionn(e[i].x,e[i].y);
        if(flag){
            printf("%.2lf",e[i].l);
            return ;//写在里面,因为要不同的部落距离;
            }   
        }
    }
}
double measure(int a,int b)//求欧几里得距离
{
    return sqrt(pow((ass[a].x-ass[b].x),2)+pow((ass[a].y-ass[b].y),2));
}

int main()
{
    n = read(),k = read();
    for(int i=1;i<=n;i++)
        ass[i].x = read(),ass[i].y = read();
    o = 0;//边数;
    for(int i=1;i<=n;i++)
        for(int j=1;j<i;j++)
        {
            if(i!=j)e[++o].x=i,e[o].y=j,e[o].l=measure(i,j); //为所有的点建边;
        }
    for(int i=1;i<=n;i++)
        fa[i] = i;
    sort(e+1,e+1+o,cmp);
    kruskal();   
    return 0;
}

 

  

 

以上是关于P4047 [JSOI2010]部落划分的主要内容,如果未能解决你的问题,请参考以下文章

P4047 [JSOI2010]部落划分

1821: [JSOI2010]Group 部落划分 Group

P4047 部落划分

1821: [JSOI2010]Group 部落划分 Group

BZOJ1821: [JSOI2010]Group 部落划分 Group

洛谷 1821: [JSOI2010]Group 部落划分 Group