链接 : http://acm.hdu.edu.cn/showproblem.php?pid=1875
最小生成树,特殊点在于给出坐标自己算距离,double型,Prim比较省时
给出Prim和Kruskal,注意Kruskal存的是边(100*100),所以结构体要开大
Prim:
#include<cstdio>
#include<cmath>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
bool used[101];
double map[101][101],a[101][2];
double Prim(int n)
{
memset(used,0,sizeof(used));
int T=n-1,k;
double min,sum=0;
used[1]=1;
while(T--)
{
min=INF;
for(int i=1;i<=n;i++)
if(!used[i] && min>map[1][i])
min=map[1][k=i];
if(min==INF) return -1;
used[k]=1;
sum+=min;
for(int i=1;i<=n;i++)
if(!used[i] && map[k][i]<map[1][i])
map[1][i]=map[k][i];
}
return sum;
}
int main()
{
int T,n;
scanf("%d",&T);
while(T-- && scanf("%d",&n))
{
for(int i=1;i<=n;i++)
{
scanf("%lf %lf",&a[i][0],&a[i][1]);
for(int j=1;j<=n;j++)
map[i][j]= i==j ? 0 : INF;
}
for(int i=1;i<=n;i++) //计算各点间的距离
for(int j=i+1;j<=n;j++)
{
double dis=sqrt((a[i][0]-a[j][0])*(a[i][0]-a[j][0])+(a[i][1]-a[j][1])*(a[i][1]-a[j][1]));
if(dis>=10 && dis<=1000 && map[i][j]>dis)
map[i][j]=map[j][i]=dis;
}
double ans=Prim(n);
printf(ans<0 ? "oh!\n" : "%.1f\n",ans*100);
}
return 0;
}
Kruskal:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
struct node
{
double s,e,dis;
}s[10001];
int father[101];
bool cmp(node a,node b)
{
return a.dis<b.dis;
}
int find(int n)
{
return n==father[n] ? n : father[n]=find(father[n]);
}
int main()
{
int T,c;
scanf("%d",&T);
while(T-- && scanf("%d",&c))
{
double a[101][2];
int k=0;
for(int i=1;i<=c;i++)
{
father[i]=i;
scanf("%lf %lf",&a[i][0],&a[i][1]);
}
for(int i=1;i<=c;i++) //计算
for(int j=i+1;j<=c;j++)
{
double d=sqrt((a[i][0]-a[j][0])*(a[i][0]-a[j][0])+(a[i][1]-a[j][1])*(a[i][1]-a[j][1]));
if(d>=10 && d<=1000)
{
s[k].s=i;
s[k].e=j;
s[k++].dis=d;
}
}
sort(s,s+k,cmp);
double sum=0;
for(int i=0;i<k;i++)
{
int x=find(s[i].s);
int y=find(s[i].e);
if(x!=y)
{
sum+=s[i].dis;
father[y]=x;
}
}
int flag=0;
for(int i=1;i<=c;i++) //判连通
{
if(father[i]==i) flag++;
if(flag>1) break;
}
printf(flag>1 ? "oh!\n" : "%.1f\n",sum*100);
}
return 0;
}