题目:http://poj.org/problem?id=1639
对根的度数有限制的最小生成树;
先忽略根,跑最小生成树,得到几个连通块,再一一与根连上;
然后在限制内用根连出去的边来使生成树更小,这需要枚举边以及用dp维护树上边的dfs序之前最大的一个;
此题用邻接矩阵比较方便。
改了一晚上,终于发现是混淆了n和cnt,cnt才是点数。
邻接表失败版:
#include<iostream> #include<cstdio> #include<map> #include<cstring> #include<algorithm> using namespace std; int n,m,head[25],ct=1,cnt,ed,fa[25],cost,reg; char s1[15],s2[15]; map<string,int>mp; struct N{ int to,next,w; N(int t=0,int n=0,int ww=0):to(t),next(n),w(ww) {} }edge[50],e[25]; struct NN{ int v,bh; }dp[25]; bool use[50],use2[50],lk[25],vis[25]; bool cmp(N x,N y){return x.w<y.w;} int find(int x) { if(x==fa[x])return x; return fa[x]=find(fa[x]); } void kruskal() { sort(edge+2,edge+ct+1,cmp); for(int i=1;i<=n;i++)fa[i]=i; for(int i=2;i<=ct;i+=2) { int u=edge[i].to; int v=edge[i^1].to; if(find(u)!=find(v)) { cost+=edge[i].w; fa[find(u)]=find(v); use[i]=1; use[i^1]=1; } } } void dfs(int x) { vis[x]=1; for(int i=head[x];i;i=edge[i].next) { int u=edge[i].to; if(!use[i]||vis[u])continue; // printf("u=%d ",u); // printf("x=%d——u=%d ",x,u); if(dp[x].v>edge[i].w) { dp[u].v=dp[x].v; dp[u].bh=dp[x].bh; } else { // printf("u=%d x=%d ",u,x); dp[u].v=edge[i].w; // printf("dp[%d].v=%d ",u,dp[u].v); dp[u].bh=i; } dfs(u); } } void add(int x,int y,int z) { ct++; edge[ct].to=y; edge[ct].next=head[x]; edge[ct].w=z; head[x]=ct; } int main() { scanf("%d",&n); mp["Park"]=++cnt; for(int i=1;i<=n;i++) { int x; scanf("%s %s",&s1,&s2); scanf("%d",&x); if(!mp[s1])mp[s1]=++cnt; if(!mp[s2])mp[s2]=++cnt; if(mp[s1]==1) { e[++ed].to=mp[s2]; e[ed].w=x; continue; } if(mp[s2]==1) { e[++ed].to=mp[s1]; e[ed].w=x; continue; } // edge[++ct]=(mp[s2],head[mp[s1]],x);head[mp[s1]]=ct; // edge[++ct]=(mp[s1],head[mp[s2]],x);head[mp[s2]]=ct; add(mp[s2],mp[s1],x); add(mp[s1],mp[s2],x); } // for(int i=2;i<=ct;i++) // printf("w=%d to=%d ",edge[i].w,edge[i].to); scanf("%d",&m); kruskal(); sort(e+1,e+ed+1,cmp); for(int i=1;i<=ed;i++) { int u=e[i].to; if(!lk[find(u)]) { cost+=e[i].w; lk[find(u)]=1; use2[i]=1; reg++; } } vis[1]=1; for(int i=1;i<=ed;i++) { if(!use2[i])continue; dp[e[i].to].v=-1; dfs(e[i].to); } // for(int i=1;i<=n;i++) // printf("i=%d v=%d bh=%d ",i,dp[i].v,dp[i].bh); // for(int i=1;i<=n;i++) // printf("dp[%d]=%d ",i,dp[i].v); while(reg<m) { int mx=-10005; int d,k; for(int i=1;i<=ed&®<m;i++) { if(use2[i])continue; int u=e[i].to; if(dp[u].v-e[i].w>mx) { mx=dp[u].v-e[i].w; // cout<<dp[u].v<<" "<<e[i].w<<endl; d=u;k=i; } } // printf("mx=%d d=%d k=%d ",mx,d,k); if(mx<=0)break; cost-=mx; use[dp[d].bh]=0; use2[k]=1; reg++; dp[d].v=-1; memset(vis,0,sizeof vis); vis[d]=1; dfs(d); } printf("Total miles driven: %d ",cost); return 0; }
代码如下:
#include<iostream> #include<cstdio> #include<map> #include<cstring> #include<algorithm> #include<string> using namespace std; int n,m,ct,cnt,fa[250],cost,reg,key[250],mne[250],inf=0x3f3f3f3f; string s1,s2; map<string, int>mp; struct N{ int hd,to,w; }edge[50000]; struct NN{ int w,u,v; }dp[50000]; bool in[250][250]; int sid[250][250]; bool cmp(N x,N y){return x.w<y.w;} int find(int x) { if(x==fa[x])return x; return fa[x]=find(fa[x]); } void kruskal() { sort(edge+1,edge+ct+1,cmp); // for(int i=1;i<=ct;i++) // printf("w=%d u=%d v=%d ",edge[i].w,edge[i].hd,edge[i].to); for(int i=1;i<=cnt;i++)fa[i]=i;// for(int i=1;i<=ct;i++) { int u=edge[i].hd; int v=edge[i].to; if(u==1||v==1)continue; if(find(u)!=find(v)) { cost+=edge[i].w; fa[find(u)]=find(v); in[u][v]=in[v][u]=1; } } } void dfs(int x,int f) { for(int u=2;u<=cnt;u++) { if(!in[x][u]||u==f)continue; if(dp[u].w==-1) { if(dp[x].w>sid[x][u]) dp[u]=dp[x]; else { dp[u].w=sid[x][u]; dp[u].u=x;dp[u].v=u; } } dfs(u,x); } } int main() { scanf("%d",&n); mp["Park"]=++cnt; memset(sid,0x3f,sizeof sid); for(int i=1;i<=n;i++) { int x; cin>>s1>>s2>>x; if(!mp[s1])mp[s1]=++cnt; if(!mp[s2])mp[s2]=++cnt; int m1=mp[s1],m2=mp[s2];//! sid[m1][m2]=sid[m2][m1]=min(sid[m1][m2],x); edge[++ct].w=x; edge[ct].hd=m1;edge[ct].to=m2; } scanf("%d",&m); kruskal(); // for(int i=1;i<=cnt;i++) // for(int j=1;j<=cnt;j++) // if(in[i][j])printf("in[%d][%d]=%d ",i,j,in[i][j]); // cout<<cost<<endl; memset(mne,0x3f,sizeof mne); for(int i=2;i<=cnt;i++) { if(sid[i][1]==inf)continue; int cr=find(i); if(mne[cr]>sid[i][1]) { mne[cr]=sid[i][1]; key[cr]=i; } } for(int i=1;i<=cnt;i++)// { if(mne[i]==inf)continue; // cost+=mne[i]; cost+=sid[1][key[i]];// in[1][key[i]]=in[key[i]][1]=1; reg++; } for(int j=reg+1;j<=m;j++) { memset(dp,-1,sizeof dp); dp[1].w=-inf; for(int i=2;i<=cnt;i++) { if(in[i][1])dp[i].w=-inf; // else dp[i].w=-1; } dfs(1,-1); int mn=inf; int d; for(int i=2;i<=cnt;i++) { // if(sid[i][1]==inf)continue; if(sid[i][1]-dp[i].w<mn) { mn=sid[i][1]-dp[i].w; d=i; } } if(mn>=0)break; cost+=mn; in[dp[d].u][dp[d].v]=in[dp[d].v][dp[d].u]=0; in[1][d]=in[d][1]=1; } printf("Total miles driven: %d ",cost); return 0; }