poj 1639 Picnic Planning

    技术2023-03-19  45

    这是一个 最小k度限制生成树 的题,看了国家集训队2004汪汀的论文,感觉他没有写彻底,求出最小m度限制生成树,扩展到m+1后,best数组应该要跟新,然后才能去扩展m+2,依次类推,直到度数为k。

    sign[]:记录已和v0相连得节点。

    best[]:记录v---v0路径上与v0无关联且权值最大的边,利用动态规划求得,且要跟新。

    #include<iostream> #include<cstdlib> #include<cstring> using namespace std; #define N 25 #define max_int 99999999 int sign[N],cost[N][N],dist[N],s[N],pi[N],best[N]; int weight; char nam[N][15]; struct Edge { char a[15],b[15]; int dist; }; Edge e[N*N]; char temp[N*N][15]; int choose(int n) { int m=max_int,pos=-1; for(int i=1;i<=n;i++) if(dist[i]<m&&!s[i]) { m=dist[i]; pos=i; } return pos; } int mymax(int a,int b) { if(a>b) return a; else return b; } void prim(int v,int v0,int n)//每个连通分量的最小生成树 { int u,i; dist[v]=cost[v][v0]; pi[v]=v0; while(1) { u=choose(n); if(u==-1) break; if(pi[u]!=v0) best[u]=mymax(best[pi[u]],cost[pi[u]][u]);//动态规划求得best s[u]=1; weight+=dist[u]; for(i=1;i<=n;i++) if(!s[i]&&dist[i]>cost[u][i]) { pi[i]=u; dist[i]=cost[u][i]; } } } void aprim(int n,int v0)//m度扩展到m+1度后,对best进行更新 { //方法就是再求一次最小生成树,每次v0是m+1度,m+2度....k度 int u,i; while(1) { u=choose(n); if(u==-1) break; if(pi[u]!=v0) best[u]=mymax(best[pi[u]],cost[u][pi[u]]); s[u]=1; for(i=1;i<=n;i++) if(!s[i]&&i!=v0&&dist[i]>cost[u][i]) { pi[i]=u; dist[i]=cost[u][i]; } } } void deg_prim(int v0,int k,int n) { int i,j,t=0,degmst,m,pos,r,c,h; for(i=1;i<=n;i++) if(cost[v0][i]<max_int) best[i]=-max_int; memset(sign,0,sizeof(sign)); for(i=1;i<=n;i++) dist[i]=max_int; best[v0]=-max_int; pi[v0]=v0; s[v0]=1; for(h=1;h<=n;h++)//求m个连通分量的最小生成树 for(i=1;i<=n;i++) if(cost[v0][i]<max_int&&!s[i]) { m=cost[v0][i]; pos=i; for(j=1;j<=n;j++) if(cost[v0][j]<m&&!s[j]) { m=cost[v0][j]; pos=j; } prim(pos,v0,n); sign[pos]=1; t++; } degmst=weight;//weight保存了最小m度生成树的权值 for(j=1;j<=k-t;j++)//直到k度为止 { m=max_int; for(i=1;i<=n;i++) if(cost[v0][i]<max_int&&!sign[i]) { if(m>degmst+cost[v0][i]-best[i]) { m=degmst+cost[v0][i]-best[i]; pos=i; } } degmst=m; if(degmst<weight) weight=degmst; sign[pos]=1; //为best更新初始化必要的数据 pi[pos]=v0; best[pos]=-max_int; for(i=1;i<=n;i++) { if(i!=v0) { s[i]=0; if(sign[i]) dist[i]=0; else dist[i]=max_int; } } aprim(n,v0); } } int cmp(const void *a,const void *b) { return strcmp((char*)a,(char *)b); } int mysearch(char source[][15],char key[],int n) { int mid,left=1,right=n; while(left<=right) { mid=(left+right)/2; if(strcmp(key,source[mid])==0) return mid; else if(strcmp(key,source[mid])>0) left=mid+1; else right=mid-1; } } int main() { int n,i,h=0,k=1,j,a,b,c; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%s%s%d",e[i].a,e[i].b,&e[i].dist); strcpy(temp[h],e[i].a); strcpy(temp[h+1],e[i].b); h+=2; } qsort(temp,h,sizeof(temp[0]),cmp); strcpy(nam[1],temp[0]); for(i=1;i<h;i++) if(strcmp(temp[i],temp[i-1])) strcpy(nam[++k],temp[i]); for(i=1;i<=k;i++) for(j=i;j<=k;j++) cost[i][j]=cost[j][i]=max_int; for(i=1;i<=n;i++) { a=mysearch(nam,e[i].a,k); b=mysearch(nam,e[i].b,k); if(e[i].dist<cost[a][b]) cost[a][b]=cost[b][a]=e[i].dist; } scanf("%d",&c); weight=0; deg_prim(mysearch(nam,"Park",k),c,k); printf("Total miles driven: %d/n",weight); return 0; }

    最新回复(0)