题意:连接一些N个点,生成树,前提是M对点已经连接
解法:Prim算法,因为点有1000个,生成的边就会很庞大
prim算法的核心就是:在生成树外找最近的点,加入就好了。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<iomanip>
#include<list>
#include<deque>
#include<map>
#include <stdio.h>
#include <deque>
#define maxn 1005
#define ull unsigned long long
#define rep(i,n) for(i=0;i<n;i++)
#define cle(a) memset(a,0,sizeof(a))
#define mod 90001
const ull inf = 1 << 30;
using namespace std;
struct node
{
double x,y;
}tree[maxn];
bool cmp(int a,int b){
return a>b;
}
//prime
int n,m;
double getdis(node a ,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double mapp[maxn][maxn];
double getprime()
{
int used[maxn];
cle(used);
int pos=1;
used[1]=1;
int i,j,k;
double low[maxn];
for(i=1;i<=n;i++)
{
if(i==pos)continue;
low[i]=mapp[pos][i];
}
double ans=0;
for(i=1;i<n;i++)
{
double min=100000000;
int k;
for(j=1;j<=n;j++)
{
if(used[j]==0&&min>low[j])
{
min=low[j],k=j;
}
}
ans+=min;
used[k]=j;
for(j=1;j<=n;j++)
{
if(used[j]==0&&low[j]>mapp[k][j])
{
low[j]=mapp[k][j];
}
}
}
return ans;
}
int main()
{
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(cin>>n>>m)
{
int i,j,k;
for(i=1;i<=n;i++)
{
scanf("%lf%lf",&tree[i].x,&tree[i].y);
}
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
mapp[i][j]=getdis(tree[i],tree[j]);
mapp[j][i]=mapp[i][j];
}
}
for(i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
mapp[a][b]=mapp[b][a]=0;
}
double ans=getprime();
printf("%.2lf\n",ans);
}
return 0;
}