题意:
最小生成树
思路:
1.求出每两点之间的距离,去一个点最为根,将所有点的距离初始化为到根的距离
2.求出未考虑的点到已考虑的点的最短距离,并标记这个点为已考虑(里层循环),每纳入一个新点,就调整未考虑的点到已考虑的点的最短距离
3.2执行n此或者到找不到可纳入的点
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
const int inf = 0xFFFFFFF;
const int N = 105;
int n;
int vis[N];
double x[N], y[N], g[N][N];
double dis(double x1, double y1, double x2, double y2) {
return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
}
double ans, d[N];
void prim() {
int x = 0;
double m;
memset(vis, 0, sizeof(vis));
vis[0] = 1;
ans = 0;
for(int i=0; i<n; i++)
d[i] = g[0][i];
d[0] = 0;
for(int i=0; i<n; i++) {
m = inf;
for(int j=0; j<n; j++) {
if(d[j] < m && !vis[j]) {
x = j;
m = d[j];
}
}
if(m == inf) break;
ans += m;
vis[x] = 1;
for(int j=0; j<n; j++) {
if(d[j] > g[x][j] && !vis[j])//到里面的点即可
d[j] = g[x][j];
}
}
printf("%.2lf\n", ans);
}
int main() {
int kase;
scanf("%d", &kase);
while(kase--) {
scanf("%d", &n);
for(int i=0; i<n; i++)
scanf("%lf%lf", &x[i], &y[i]);
for(int i=0; i<n; i++)
for(int j=0; j<n; j++) {
if(i != j)
g[i][j] = dis(x[i], y[i], x[j], y[j]);
}
prim();
if(kase) printf("\n");
}
return 0;
}