菜鸟生成记(60)
这一题就是最小生成树绕了一个小弯,
模板题:直接给出结点数和边数;以及边的两个顶点和边权;
这一题:给出n个坐标(x,y),这n个坐标就代表n个结点;通过两点间的距离公式sqrt(pow(x1-x2,2)+pow(y1-y2,2))求出每个点其他结点的距离(边权);然后按边权的升序把这些边排序;然后选取n-1个边构成最小生成树
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
const int N=1e6+10;
int pre[N]={0};
struct st{
int i,j;
double w;
bool operator<(const st &a)const
{
return w<a.w||false;
}
};
int find1(int x)
{
int t=x;
while(pre[t]!=t)
{
t=pre[t];
}
return t;
}
int main()
{
st s[N];
st t[N];
int n,m1,k=0,num=0;
double sum=0;
cin>>n>>m1;
for(int i=1;i<=n;i++)
pre[i]=i;
for(int i=1;i<=n;i++)
{
cin>>s[i].i>>s[i].j;
}
for(int i=1;i<=n-1;i++)
{
sum=0;
for(int j=i+1;j<=n;j++)
{
int x,y,y1,x1;
x=s[i].i;
y=s[i].j;
x1=s[j].i;
y1=s[j].j;
sum=sqrt(pow((double)(x-x1),2)+pow((double)(y-y1),2));
t[k].i=i;
t[k].j=j;
t[k++].w=sum;
}
}
sort(t,t+k);
for(int i=0;i<m1;i++)
{
int t1,t2,u,v;
scanf("%d%d",&u,&v);
t1=find1(u);
t2=find1(v);
if(t1!=t2)
{
pre[t1]=t2;
num++;
}
}
sum=0;
for(int i=0;i<k;i++)
{
int t1,t2,u,v;
u=t[i].i;
v=t[i].j;
t1=find1(u);
t2=find1(v);
if(t1!=t2)
{
pre[t1]=t2;
sum+=t[i].w;
num++;
}
if(num==n-1)
break;
}
printf("%.2lf\n",sum);
return 0;
}