题意:给出n个点和他们的坐标,用一支墨水笔将他们连通,要求墨水浪费最少
典型的最小生成树问题,用kruskal问题(包括并查集)
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
typedef struct Node{
int s; // 起点
int d; // 终点
double dis; // 距离
}Edge; // 边结构体
Edge E[4950]; // 100个点最多4950条边
int father[100];
int n; // 点个数
int cnt = 0; // 边个数
void init()
{
for(int i = 0;i<n;i++)
father[i] = i;
}
int findfather(int n)
{
if(father[n] == n)
return n;
else
return findfather(father[n]);
}
int cmp(const void*a,const void*b)
{
Edge *x = (Edge *)a;
Edge *y = (Edge *)b;
return x->dis*1000 - y->dis*1000;
}
double kruskal()
{
double ans = 0;
qsort(E,cnt,sizeof(Edge),cmp);
int j = 0; // 已添加的边的个数
for(int i = 0;i<cnt;i++)
{
if(j == n-1)
break;
int x,y;
//合并
x = findfather(E[i].s);
y = findfather(E[i].d);
if(x!=y)
{
father[x] = y;
ans += E[i].dis;
j++;
}
else
continue;
}
return ans;
}
int main()
{
scanf("%d",&n);
double c[n][2];
init(); // father初始化
for(int i = 0;i<n;i++)
scanf("%lf%lf",&c[i][0],&c[i][1]);
for(int i = 0;i<n;i++)
{
for(int j = i+1;j<n;j++)
{
E[cnt].s = i;
E[cnt].d = j;
E[cnt].dis = sqrt( (c[i][0]-c[j][0]) * (c[i][0]-c[j][0]) + (c[i][1]-c[j][1]) * (c[i][1]-c[j][1]) );
cnt ++;
}
}
printf("%.2lf",kruskal());
return 0;
}
京公网安备 11010502036488号