HDU 3405 World Islands (prim算法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3405
【题目大意】
给你n个点的坐标,忽视其中一个点,求余下点的最小生成树。
我们不知道忽视的是哪一个点,所以要进行n次最小生成树。
prim算法需要使用一个标记数组 intree ,我们只要把忽视的那个点放入intree就不会扫描了;
【源代码】
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int maxn = 55; struct node{ int x,y; }PP[maxn]; const double INF = 100000000.0; double G[maxn][maxn]; bool intree[maxn]; double minDist[maxn]; int n; double distane(node a,node b){ return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y)); } double prim(int x){ double sum=0; intree[x]=1; if(x!=0){//如果忽视的点不是 0 for(int i=0;i<n;i++){ //起点置为 0 minDist[i]=G[i][0]; } intree[0]=1; } else{ //否则 for(int i=0;i<n;i++){ //起点置为1 minDist[i]=G[i][1]; } intree[1]=1; } for(int nodeNum=1;nodeNum<n-1;nodeNum++){ //注意这里要找的点只有n-2个点 double tmpMin=INF; int addNode=-1; for(int i=0;i<n;i++){ if(!intree[i]&&minDist[i]<tmpMin){ tmpMin = minDist[i]; addNode = i; } } if(tmpMin==INF) { return -1; } sum+=tmpMin; intree[addNode]=1; for(int i=0;i<n;i++){ if(!intree[i]&&G[addNode][i]<minDist[i]) minDist[i]=G[addNode][i]; } } if(sum!=0) return sum; return -1; } void init(){ for(int i=0;i<maxn;i++) for(int j=0;j<maxn;j++) G[i][j]=INF; } int main(){ int T; scanf("%d",&T); while(T--){ init(); scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d%d",&PP[i].x,&PP[i].y); } for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ double dis = distane(PP[i],PP[j]); G[i][j]=min(G[i][j],dis); G[j][i]=min(G[j][i],dis); } } double ans=INF; for(int i=0;i<n;i++){ memset(intree,0,sizeof(intree)); for(int j=0;j<maxn;j++) minDist[j]=INF; //这里要初始化 double tmp = prim(i); if(tmp!=-1) ans=min(tmp,ans); } printf("%.2lf\n",ans); } return 0; }