P4047 部落划分

  这题太水了吧,不知道怎么蓝的,蒟蒻只写了十五分钟就一次AC了……

  但是挺有意思,就发篇题解吧qwq

  emmm……最小生成树(贪心),就没别的了……

  要明确:

  一开始可以把每个点都看成一个部落,那么每一次连一条不相通的边时,就相当于合并了两个部落。

  那么当剩下k个部落的时候,找下一条边即可。

  有一个要注意:

  就是当已经找完所有边时,不能直接输出第i+1条,而是要继续找直到找到下一条合法边(原因很简单,就不解释了……)

  代码代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
#define maxn 1000005
//#define int double
int n,k,cnt;
int nx[1005],ny[1005],par[maxn];
struct node
{
    int from,to;
    double w;
} q[maxn];
bool cmp(node a,node b)
{
    return a.w<b.w;
}
double use(int x,int y,int xx,int yy)
{
    return sqrt( pow(x-xx,2)+pow(y-yy,2) );
}
void add(int x,int y,double e)
{
    q[++cnt].to=y;
    q[cnt].from=x;
    q[cnt].w=e;
}
int find(int x)
{
    return x==par[x] ? x : par[x]=find(par[x]);
}
void merge(int x,int y)
{
    par[find(y)]=find(x); 
}
void kruskal()
{
    for(int i=1;i<=cnt;i++)
    {
        int nowx=q[i].from,nowy=q[i].to;
        if(find(nowx)==find(nowy))
            continue;
        merge(nowx,nowy);
        n--;
        if(n==k-1)
        {
            printf("%.2lf",q[i].w);
            break;
        }
    }
}
main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        par[i]=i;
    for(int i=1;i<=n;i++)
        scanf("%d%d",&nx[i],&ny[i]);
    for(int i=1;i<=n;i++)
    for(int j=1;j<i;j++)
    {
        double e=use(nx[i],ny[i],nx[j],ny[j]);
        add(i,j,e);
        add(j,i,e);
    }
    sort(q+1,q+cnt+1,cmp);
    kruskal();
    return 0;
}

  这么简单的题要不去直接AC吧~

原文地址:https://www.cnblogs.com/popo-black-cat/p/10067917.html