Aizu2224

题意:一个邪恶的女巫因为嫉妒Nicholas家的猫可爱,就施了魔法让他家的猫咪困在卷子里出不来了(要不然说她邪恶呢)。现在给出她施魔法变出来的桩的坐标,栅栏i与栅栏j(是一个整体,也就是给出了一条边,边的长度是第i个桩与第j个桩间的长度)。现在让你求最少需要破坏多长的栅栏才能让可爱的猫咪都出来。

分析:若想要让猫咪出来的话,肯定是不能有环了。那么现在就有一个思想:算出全部边长总和,然后减去可以构成的最大生成树的总和(不能有环,生成树正好符合这样的条件,再加额外的边就会产生环),那么剩下的就是需要被破坏的边的总和。但是怎样求最大生成树呢?我们需要用到并查集,首先将边存在结构体里,然后按照从大到小将边长排序,接着需要遍历m条边,当加入某条边时,若两端的father[x]不同,则需要进行归并(father[x]=y),若相同的话,自然不需要加它这条边的边长了(相同的话,会构成一个封闭区间)。

注意:没有说m的范围,在开有关m的数组时,需要比n大。
以及,并查集一定要记得初始化!!!!

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
struct edge{
    int a1,a2;
    double cost;
}G[100000];
bool cmp(edge a,edge b)
{
    return a.cost>b.cost;
}
int par[10005];
int find(int x)
{
    return par[x]==x?x:par[x]=find(par[x]);
}
bool unite(int x,int y)
{
    x=find(x),y=find(y);
    if(x==y)return false;
    par[x]=y;
    return true;
}
int main()
{
    int n,m,i,j,k;
    cin>>n>>m;
    int x[10005],y[10005];
    for(i=1;i<=n;i++)
        scanf("%d %d",&x[i],&y[i]);
    for(i=1;i<=n;i++)par[i]=i;//初始化!!!!!
    double total=0;
    for(i=1;i<=m;i++){
        int a,b;cin>>a>>b;double t=sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
        G[i].a1=a,G[i].a2=b,G[i].cost=t;
        total+=t;
    }
    sort(G+1,G+1+m,cmp);
    int cnt=0;double len=0;
    for(i=1;i<=m;i++){
        if(unite(G[i].a1,G[i].a2))
            cnt++,len+=G[i].cost;
        if(cnt==n-1)break;
    }
    printf("%.3f\n",total-len);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值