HDU 3405 World Islands 最小生成树变形
http://acm.hdu.edu.cn/showproblem.php?pid=3405
给出n个点,求把任意n-1个点连起来的最短路(n<50) ,开始不想把每个点都去一遍,因为那样就会构造n个最小生成树,怕超时。。。。有好多想法,如求出最小生成树在把书中最大的边去掉,但是这样可能把树分成两个部分,每部分点数都不是1。后来想用kruscal,把边从小到大加n-2条到树中,但是这样可能不会形成一个树。 最后还是把每个点都去一边,生n-1个最小生成树A掉的,对时间复杂度还是不了解啊 导致许多枚举,遍历等不敢做。 prim时间复杂度 O(n2)
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> const int inf=99999991; using namespace std; double map[55][55],dis[55]; int n; bool vs[55]; struct Node { int x,y; }node[55]; double Min(double a,double b) { if(a>b)return b; else return a; } double prim(int x) { int i,k,mark; memset(vs,0,sizeof(vs)); vs[x]=1; for(i=0;i<n;i++) { dis[i]=map[i][0]; }vs[0]=1; if(x==0) { for(i=0;i<n;i++){ dis[i]=map[i][1]; }vs[1]=1; } double MIN,SUM=0; for(k=1;k<n-1;k++) { MIN=inf; for(i=0;i<n;i++) if(!vs[i]&&MIN>dis[i]) { MIN=dis[i]; mark=i; } SUM+=MIN; vs[mark]=1; for(i=0;i<n;i++) if(!vs[i]&&dis[i]>map[mark][i]) dis[i]=map[mark][i]; } return SUM; } int main() { int i,j,CASE; double d,x1,y1; scanf("%d",&CASE); while(CASE--) { scanf("%d",&n); for(i=0;i<n;i++) { map[i][i]=0; scanf("%d%d",&node[i].x,&node[i].y); for(j=i-1;j>=0;j--) { x1=node[i].x-node[j].x; y1=node[i].y-node[j].y; d=sqrt(x1*x1+y1*y1); map[i][j]=map[j][i]=d; } } double h,g=inf; for(i=0;i<n;i++) { h=prim(i); g=Min(g,h); } printf("%.2lf\n",g); } return 0; }