题意:给出n个坐标,求出最短的路径使这n个点相连。其中有两个点必须连。
思路:裸的最小生成树。需要注意的就是对这两个点特殊处理。
如果用prim的话,需要将所有与这两个点相连的边加入。如果是krusal就没有什么吧。。
(好久没有打了。。手残了好几发)
代码如下:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <utility>
#include <queue>
using namespace std;
typedef pair<double,int> pdi;
const int MAX = 55;
double x[MAX];
double y[MAX];
double d[MAX][MAX];
bool used[MAX];
int p,q;
priority_queue<pdi> pq;
int main(void)
{
//freopen("input.txt","r",stdin);
int N;
while(scanf("%d",&N), N){
scanf("%d %d",&p,&q);
for(int i = 1; i <= N; ++i)
scanf("%lf %lf", &x[i], &y[i]);
for(int i = 1; i <= N; ++i){
for(int j = 1; j <= i; ++j)
d[i][j] = d[j][i] = sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
}
double ans = d[p][q];
memset(used,0,sizeof(used));
used[p] = used[q] = true;
for(int i = 1; i <= N; ++i){
pq.push(pdi(-d[p][i],i));
//pq.push(pdi(-d[q][i],i));
}
while(!pq.empty()){
pdi info = pq.top();pq.pop();
double di = -info.first;
int u = info.second;
if(used[u]) continue;
//printf("%.2f %d\n",di,u);
used[u] = true;
ans += di;
for(int i = 1; i <= N; ++i)
if(!used[i])
pq.push(pdi(-d[u][i],i));
}
printf("%.2f\n",ans);
}
return 0;
}