有N个树桩的坐标,然后下面给出其中的M条边,边围成环时,要去掉每个环中的最小的一条边,把问题转化为求最大生成树,并记录边权值的和,所有边的和减去生成树的和
边的数组要开到大于10000*10000/2.不然Runtime Error
代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 10010
using namespace std;
int per[MAXN];
struct node
{
int a;
int b;
double edge;
};
node es[MAXN*MAXN];//最多能形成10000*10000/2 条边
bool cmp(node x,node y)
{
return x.edge>y.edge;
}
int find(int x)
{
if(per[x]==x)
return x;
return per[x]=find(per[x]);
}
double ans;
double kruskal(int n,int m)
{
sort(es,es+m,cmp);
ans=0;
int cnt=0;
for(int i=0;i<m&&cnt<n-1;i++)
{
int fx=find(es[i].a);
int fy=find(es[i].b);
if(fx!=fy)
{
per[fx]=fy;
ans+=es[i].edge;
cnt++;
}
}
return ans;
}
int main()
{
int n,m;
double pointx[10000+10],pointy[10000+10];
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
{
per[i]=i;
}
double sum=0.0;
for(int i=1;i<=n;i++)
scanf("%lf%lf",&pointx[i],&pointy[i]);
for(int i=0;i<m;i++)
{
scanf("%d%d",&es[i].a,&es[i].b);
es[i].edge=sqrt((pointx[es[i].a]-pointx[es[i].b])*(pointx[es[i].a]-pointx[es[i].b])+(pointy[es[i].a]-pointy[es[i].b])*(pointy[es[i].a]-pointy[es[i].b]));
sum+=es[i].edge;
}
printf("%.4lf\n",sum-kruskal(n,m));
}
return 0;
}