题目链接:点击打开链接
题意:求一个图中忽略某个点的最小生成树的最小值
用prim算法求解,要忽略某个点只需在进行prim算法前将这个点的vis[]改为true即可,此时开始prim算法的原点不能是这个点,否则算法将无法继续(没有另一个点初始dis小于inf,无法更新其他点的dis)。
pow函数中两个参数形式需一致,不然会ce。
代码:
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
using namespace std;
double a[60][60];
int x[60];
int y[60];
double dis[60];
bool bill[60];
bool vis[60];
int n;
const double inf=100000000;
double Dis(int x1,int y1,int x2,int y2){
return pow(double((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)),0.5);
}
double prim(int src){
double res=0;
for(int i=1;i<=n;i++){
dis[i]=inf;
}
dis[src]=0;
for(int j=1;j<=n;j++){
double tmp=inf;int k=src;
for(int i=1;i<=n;i++){
if(!vis[i]&&dis[i]<tmp){
tmp=dis[i];
k=i;
}
}
vis[k]=1;
res+=dis[k];
//cout<<k<<" "<<dis[k]<<" "<<res<<endl;
for(int i=1;i<=n;i++){
if(!vis[i]&&dis[i]>a[k][i]){
dis[i]=a[k][i];
}
}
}
return res;
}
void init(){
memset(vis,0,sizeof(vis));
memset(bill,0,sizeof(bill));
}
int main()
{
int T;
cin>>T;
while(T--){
double res=100000000;
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
a[i][j]=Dis(x[i],y[i],x[j],y[j]);
}
}
for(int i=1;i<=n;i++){
init();
vis[i-1]=0;
vis[i]=1;
res=min(res,prim(i-1==0?n:i-1));
}
printf("%.2lf\n",res);
}
return 0;
}