典型的最小生成树,直接套prim写的
题意要求是有一条边一定要加入MST中
所以我们可以先令这条边的权值为0
最后计算出来的结果再加上这条边原来的权值
代码如下:
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
#define MAXN 1010
#define LL long long
#define INF 0x7fffffff
using namespace std;
int n;
struct POS{
double x, y;
}pos[MAXN];
double dis[MAXN];
double g[MAXN][MAXN];
double prim() {
int now, i, j;
int minnode;
double ans, minedge;
for(i=1; i<=n; ++i)
dis[i] = INF;
now = 1;
ans = 0;
for(i=1; i<n; ++i) {
dis[now] = -1;
minedge = INF;
for(j=1; j<=n; ++j) {
if(now!=j && dis[j]>=0) {
dis[j] = min(dis[j], g[now][j]);
if(dis[j] < minedge) {
minedge = dis[j];
minnode = j;
}
}
}
now = minnode;
ans += minedge;
}
return ans;
}
double get_dis(int i, int j) {
double tmp1 = (pos[i].x-pos[j].x)*(pos[i].x-pos[j].x);
double tmp2 = (pos[i].y-pos[j].y)*(pos[i].y-pos[j].y);
return sqrt(tmp1+tmp2);
}
int main(void) {
int p, q;
while(scanf("%d", &n) && n) {
scanf("%d%d", &p, &q);
for(int i=1; i<=n; ++i) {
scanf("%lf%lf", &pos[i].x, &pos[i].y);
}
for(int i=1; i<=n; ++i) {
for(int j=i+1; j<=n; ++j) {
g[i][j] = g[j][i] = get_dis(i, j);
}
}
double tmp = g[p][q];
g[p][q] = g[q][p] = 0.0;
printf("%.2lf\n", prim()+tmp);
}
return 0;
}