BZOJ1821 [JSOI2010]Group 部落划分 贪心+并查集

平面上有N个部落,使划分成K个居住点后,最近的两个居住点之间的距离最远。两个部落的距离,定义为部落中距离最近的那两个居住点的距离。求这个距离。

将完全图的边按照距离从小到大排序,选中边的两端用并查集并起来,第N-K+1条边的长度即为答案.

这个题目不需要二分,贪心比较巧妙

#include <bits/stdc++.h>
#define LL long long
#define clr(x,i) memset(x,i,sizeof(x)) 
using namespace std;
const int N=1005;
struct Edge{
    int u,v;
    double dist;
    friend bool operator <(Edge a,Edge b){
        return a.dist<b.dist;
    }
}e[N*N*2];
int n,K,tot,fa[N];
double x[N],y[N];
inline double Dis(int a,int b)
{
    return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
}
inline void Add(int u,int v)
{
    e[++tot].u=u;e[tot].v=v;e[tot].dist=Dis(u,v);
}
int find(int v)
{
    return fa[v]==v ? v : fa[v]=find(fa[v]);
}
int main()
{
    scanf("%d%d",&n,&K);
    for(int i=1;i<=n;i++)
      scanf("%lf%lf",&x[i],&y[i]);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)if(i!=j)
        Add(i,j);
    sort(e+1,e+tot+1);
    for(int i=1;i<=n;i++)fa[i]=i;
    int cnt=0;
    for(int i=1;i<=tot;i++)
    {
        int x=find(e[i].u),y=find(e[i].v);
        if(x!=y){
            cnt++;fa[x]=y;
            if(cnt==n-K+1){
                printf("%.2lf",e[i].dist);
                break;
            }
        }
    }
    return 0;
}




猜你喜欢

转载自blog.csdn.net/wolf_reiser/article/details/78881180