题意:
猫被栏杆围住了,使所有的猫出来,去掉栏杆长度最小是多少。
思路:即留下的树尽可能大,即sum-最大生成树的长度和,double存边即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=10000+100;
const int maxm=10010*10010;
int pre[maxn];
int n,m;
double a[maxn],b[maxn];
struct node
{
int u,v;
double w;
}edge[maxm+100];
int findd(int x)
{
int r=x;
while(r!=pre[r])
r=pre[r];
int i=x,j;
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
void join(int x,int y)
{
int tx,ty;
tx=findd(x),ty=findd(y);
if(tx!=ty)
{
pre[ty]=tx;
}
}
int cmp(node aa,node bb)
{
return aa.w>bb.w;
}
double zyz()
{
double sum=0;
int i;
for(i=1;i<=m;i++)
{
int tx,ty;
tx=findd(edge[i].u);
ty=findd(edge[i].v);
if(tx!=ty)
{
sum+=edge[i].w;
pre[tx]=ty;
}
}
//printf("%d\n",sum);
return sum;
}
int main ()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
{
pre[i]=i;
}
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&a[i],&b[i]);
}
double ans=0;
for(int i=1;i<=m;i++)
{
int xx,yy;
scanf("%d%d",&xx,&yy);
edge[i].u=xx;
edge[i].v=yy;
edge[i].w=sqrt((a[xx]-a[yy])*(a[xx]-a[yy])+(b[xx]-b[yy])*(b[xx]-b[yy]));
//printf("%f\n",edge[i].w);
ans+=edge[i].w;
}
sort(edge+1,edge+1+m,cmp);
double sum=0;
sum=zyz();
// printf("%f %f\n",ans,sum);
printf("%f\n",ans-sum);
}
}