http://acm.hdu.edu.cn/showproblem.php?pid=1162
我用了俩种算法写这道题。。。
第一种:Kruskal(最小生成树)
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
using namespace std;
int father[10005], Enums, Count;
double MinL;
struct Point{
int begin;
int end;
double Dis;
}P[10005];
int Find(int k){
return father[k]==k?k:father[k]=Find(father[k]);
}
int Cmp(Point a, Point b){
return a.Dis<b.Dis;
}
double Kruskal(){
for(int i=0; i<Count; i++){
father[i] = i;
}
for(int i=0; i<Count; i++){
int a = Find(P[i].begin);
int b = Find(P[i].end);
if(a!=b){
father[b] = a;
MinL += P[i].Dis;
}
}
return MinL;
}
void Init(){
int N;
double x[100], y[100];
while(cin>>N){
for(int i=0; i<N; i++){
cin>>x[i]>>y[i];
}
MinL = 0.0;
Count=0;
for(int i=0; i<N; i++){
for(int j=i+1; j<N; j++){
P[Count].begin = i;
P[Count].end = j;
P[Count].Dis = sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
Count++;
}
}
sort(P, P+Count, Cmp);
printf("%.2lf\n", Kruskal());
}
}
int main(){
Init();
return 0;
}
第二种:Prim(最小生成树)
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define INF 0x7ffffff
struct point
{
double x,y;
};
point p[105];
int n;
double ans;
double mpt[105][105];
void prim()
{
double lowcost[105],min;
int i,j,k;
lowcost[1]=0;
for(j=2;j<=n;j++)
lowcost[j]=mpt[1][j];
for(i=2;i<=n;i++)//找到N-1条边。
{
min=INF;
for(j=1;j<=n;j++)
if(lowcost[j]<min && lowcost[j])
{
min=lowcost[j];
k=j;
}
ans+=min;
lowcost[k]=0;
for(j=1;j<=n;j++)
if(mpt[k][j]<lowcost[j] && lowcost[j]) lowcost[j]=mpt[k][j];
}
}
int main()
{
int i,j;
while(scanf("%d",&n)!=EOF)
{
ans=0;
for(i=1;i<=n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i==j) mpt[i][j]=INF;
else mpt[i][j]=sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
}
prim();
printf("%.2f\n",ans);
}
return 0;
}