GDOI模拟 Zjr506的捕猫计划

来源:互联网 发布:网络直播策划方案 编辑:程序博客网 时间:2024/04/28 06:47

Description

Zjr506很喜欢猫,某一天他突然心血来潮,想捕捉学校里活动的猫。为了捕猫,Zjr506在校园中放置了N个木桩,当他见到有猫进入他的狩猎范围后,就会以迅雷不及掩耳的速度在一些木桩之间绕上藩篱以困住这些猫。一段时间后,Zjr506在绕了M个藩篱后兴高采烈的离开了。作为正义的使者,Ztxz16不忍心看到这些猫受到折磨,于是决定拆除一些藩篱让所有的猫都逃出去。因为Zjr506的巧妙设计,藩篱不会在除木桩之外的地方相交。这些藩篱构成了一些封闭的区域,每一个区域中都有一只猫。因为Zjr506制造这些藩篱也不容易,所以Ztxz16希望拆除的藩篱总长度尽量小,现在他希望你告诉他最小的总长度。

Data Constraint

对于20%的数据:N , M <= 30

对于30%的数据:N, M <= 300

对于100%的数据:N <= 10000, M <= 50000

Solution

这是一道简单的图论题。我们可以将题目想成有n个点,现在有一些边要连,要求连边后的图是一棵树!那么显然就是最大生成树!将边排序一下做最大生成树就好了。

代码

#include<iostream>#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define ll long longusing namespace std;const int maxn=100005;int f[maxn],n,i,j,k,l,m,p,q,x,y;double t,ans,a[maxn],b[maxn],ans1;struct code{    int a,b;    double c;}c[maxn];double sqr(double x){    return x*x;}bool cmp(code x,code y){    return x.c>y.c;}int getfather(int x){    if (x==f[x]) return x;    f[x]=getfather(f[x]);    return f[x];}int main(){    freopen("data.in","r",stdin);    scanf("%d%d",&n,&m);    for (i=1;i<=n;i++)        f[i]=i;    for (i=1;i<=n;i++)        scanf("%lf%lf",&a[i],&b[i]);    for (i=1;i<=m;i++){        scanf("%d%d",&x,&y);        t=sqrt(sqr(a[x]-a[y])+sqr(b[x]-b[y]));        c[i].a=x,c[i].b=y,c[i].c=t;ans1+=t;    }    sort(c+1,c+m+1,cmp);    for (i=1;i<=m;i++){        x=getfather(c[i].a);y=getfather(c[i].b);        if (x!=y){            f[x]=y;            ans+=c[i].c;        }    }    ans=ans1-ans;    printf("%.7lf",ans);}
3 0