链接:点击打开链接
题意:已知一条边必须连接,求最小生成树
代码:
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
double d[105],s[105][105];
int n,x[105],y[105],vis[105];
double cal(int i,int j){
return sqrt((x[i]-x[j])*(x[i]-x[j])*1.0+(y[i]-y[j])*(y[i]-y[j])*1.0);
}
double prim(int S,int T){
int i,j,u;
double v,ans;
ans=0;
for(i=1;i<=n;i++)
vis[i]=0,d[i]=INF*1.0;
vis[S]=vis[T]=1;
for(i=1;i<=n;i++) //直接更新S,T周围的值
d[i]=min(s[S][i],s[T][i]);
while(1){
u=-1;
for(i=1;i<=n;i++){
if(vis[i]==0&&(u==-1||d[i]<d[u])){
u=i;
v=d[i];
}
}
if(u==-1)
break;
ans+=v;
vis[u]=1;
for(i=1;i<=n;i++)
if(vis[i]==0)
d[i]=min(d[i],s[u][i]);
}
return ans;
}
int main(){ //直接把必须走的边直接加到已经走过的
double tt; //集合里,再prim一下
int i,j,u,v,p,q;
while(scanf("%d",&n)!=EOF&&n){
scanf("%d%d",&p,&q);
for(i=1;i<=n;i++){
scanf("%d%d",&x[i],&y[i]);
for(j=1;j<=i;j++)
s[i][j]=s[j][i]=cal(i,j);
}
tt=s[p][q];
printf("%.2lf\n",prim(p,q)+tt);
}
return 0;
}