还是最小生成树的问题。
不过这里的边需要自己求。两个循环就可以求出来。
Kruskal算法:
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
int father[105];
struct Edge
{
int u,v;
double w;
};
struct Point
{
double x,y;
};
double Distance(Point &a,Point &b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int find(int x)
{
return father[x]<0?x:(father[x]=find(father[x]));
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
Point p[105];
int n;
scanf("%d",&n);
for(int i=0;i<n;++i)
scanf("%lf%lf",&p[i].x,&p[i].y);
Edge e[10005];
int N=0;
for(int i=0;i<n-1;++i)
for(int j=i+1;j<n;++j)
{
e[N].u=i;
e[N].v=j;
e[N].w=Distance(p[i],p[j]);
N++;
}
sort(e,e+N,cmp);
memset(father,-1,sizeof(father));
double ans=0;
for(int i=0;i<N;++i)
{
Edge t=e[i];
if(find(t.u)!=find(t.v))
{
father[find(t.u)]=find(t.v);
ans+=t.w;
}
}
printf("%.2lf\n",ans);
if(T) printf("\n");
}
return 0;
}
Prim算法:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define INF 9999999999
using namespace std;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
double x[105],y[105];
for(int i=0;i<n;++i) scanf("%lf%lf",&x[i],&y[i]);
double e[105][105];
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)
e[i][j]=e[j][i]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
double mincost[105];
for(int i=0;i<n;++i) mincost[i]=INF;
bool used[105]={false};
mincost[0]=0;
double res=0;
while(1)
{
int v=-1;
for(int i=0;i<n;++i)
if(!used[i]&&(v==-1||mincost[i]<mincost[v])) v=i;
if(v==-1) break;
used[v]=true;
res+=mincost[v];
for(int i=0;i<n;++i)
mincost[i]=min(mincost[i],e[v][i]);
}
printf("%.2lf\n",res);
if(T) printf("\n");
}
return 0;
}