首页 > 代码库 > 树形dp练习
树形dp练习
/*poj 1463 最小点覆盖 匈牙利*/#include<iostream>#include<cstdio>#include<cstring>#define maxn 1510using namespace std;int n,num,head[maxn],match[maxn],c[maxn],ans;bool f[maxn];struct node{ int v,pre;}e[maxn*2];int init(){ int x=0;char s=getchar(); while(s<‘0‘||s>‘9‘)s=getchar(); while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();} return x;}void Clear(){ memset(c,0,sizeof(c)); memset(head,0,sizeof(head)); memset(match,0,sizeof(match)); num=ans=0;}void Add(int from,int to){ num++;e[num].v=to; e[num].pre=head[from]; head[from]=num;}void Dfs(int now,int from,int dep){ c[now]=dep; for(int i=head[now];i;i=e[i].pre){ int v=e[i].v; if(v==from)continue; Dfs(v,now,dep+1); }}int dfs(int u){ for(int i=head[u];i;i=e[i].pre){ int v=e[i].v; if(f[v])continue;f[v]=1; if(match[v]==0||dfs(match[v])){ match[v]=u;return 1; } } return 0;}int main(){ while(scanf("%d",&n)!=EOF){ int u,v,s;Clear(); for(int i=1;i<=n;i++){ u=init();s=init(); while(s--){ v=init();Add(u,v);Add(v,u); } } Dfs(0,-1,0); for(int i=0;i<n;i++)if(c[i]&1){ memset(f,0,sizeof(f)); ans+=dfs(i); } printf("%d\n",ans); } return 0;}
/*poj 1463 最小点覆盖 dp*/#include<iostream>#include<cstdio>#include<cstring>#define maxn 1510using namespace std;int n,num,head[maxn],f[maxn][2];struct node{ int v,pre;}e[maxn*2];int init(){ int x=0;char s=getchar(); while(s<‘0‘||s>‘9‘)s=getchar(); while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();} return x;}void Add(int from,int to){ num++;e[num].v=to; e[num].pre=head[from]; head[from]=num;}void Dfs(int x,int from){ int s=0;f[x][1]=1; for(int i=head[x];i;i=e[i].pre){ int v=e[i].v; if(v==from)continue; Dfs(v,x);s++; f[x][1]+=min(f[v][0],f[v][1]); f[x][0]+=f[v][1]; }}int main(){ while(scanf("%d",&n)!=EOF){ int u,v,s;num=0; memset(f,0,sizeof(f)); memset(head,0,sizeof(head)); for(int i=1;i<=n;i++){ u=init();s=init(); while(s--){ v=init();Add(u,v);Add(v,u); } } Dfs(0,-1); printf("%d\n",min(f[0][0],f[0][1])); } return 0;}
/*f[i][j][0/1] i子树走j步是否回到i的max*/#include<iostream>#include<cstdio>#include<cstring>#define maxn 210using namespace std;int n,m,num,head[maxn],f[maxn][maxn][2],c[maxn],ans;struct node{ int v,pre;}e[maxn*2];void Add(int from,int to){ num++;e[num].v=to; e[num].pre=head[from]; head[from]=num;}void Clear(){ num=0;ans=0; memset(f,0,sizeof(f)); memset(head,0,sizeof(head));}void Dfs(int x,int from){ f[x][0][1]=c[x]; for(int i=head[x];i;i=e[i].pre){ int v=e[i].v; if(v==from)continue; Dfs(v,x); for(int j=m;j>=0;j--) for(int k=0;k<=j;k++){ if(j-k-1>=0)f[x][j][0]=max(f[x][j][0],f[x][j-k-1][1]+max(f[v][k][0],f[v][k][1])); if(j-k-2>=0)f[x][j][0]=max(f[x][j][0],f[x][j-k-2][0]+f[v][k][1]); //这里一开始漏掉了 可以先走v 也可以最后走v if(j-k-2>=0)f[x][j][1]=max(f[x][j][1],f[x][j-k-2][1]+f[v][k][1]); } }}int main(){ while(~scanf("%d%d",&n,&m)){ Clear();int u,v; for(int i=1;i<=n;i++) scanf("%d",&c[i]); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); Add(u,v);Add(v,u); } Dfs(1,-1); for(int i=0;i<=m;i++){ ans=max(ans,f[1][i][0]); ans=max(ans,f[1][i][1]); } printf("%d\n",ans); } return 0;}
/*poj 1947*/ #include<iostream>#include<cstdio>#include<cstring>#define maxn 210#define inf 0x3f3f3f3fusing namespace std;int n,p,num,head[maxn],root,f[maxn][maxn],l[maxn],r[maxn],fa[maxn],son[maxn][maxn],sum[maxn];struct node{ int v,pre;}e[maxn];void Add(int from,int to){ num++;e[num].v=to; e[num].pre=head[from]; head[from]=num;}void Dfs(int now,int from){ fa[now]=from; for(int i=head[now];i;i=e[i].pre){ int v=e[i].v; if(v==from)continue; son[now][++son[now][0]]=v; Dfs(v,now); }}int DP(int now){ if(!now)return 0; int s=0; for(int i=1;i<=son[now][0];i++) s+=DP(son[now][i]); sum[now]=s+1; f[now][1]=son[now][0]; for(int i=1;i<=son[now][0];i++){ int x=son[now][i]; for(int j=sum[now];j>=1;j--) for(int k=1;k<=sum[x]&&k<=j;k++) f[now][j]=min(f[now][j],f[now][j-k]+f[x][k]-1); } return sum[now];}int main(){ scanf("%d%d",&n,&p); int u,v; for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); Add(u,v);Add(v,u); } Dfs(1,0);memset(f,127/3,sizeof(f)); sum[1]=DP(1);int ans=f[1][p]; for(int i=2;i<=n;i++) ans=min(ans,f[i][p]+1); printf("%d\n",ans); return 0;}
/*poj 3342 树上最大独立集+方案数统计*/#include<iostream>#include<cstdio>#include<cstring>#include<map>#define maxn 210using namespace std;int n,num,head[maxn],f[maxn][2],g[maxn][2],cnt;map<string,int>r;struct node{ int v,pre;}e[maxn*2];void Add(int from,int to){ num++;e[num].v=to; e[num].pre=head[from]; head[from]=num;}void Dfs(int x,int from){ g[x][0]=1;f[x][1]=1;g[x][1]=1; int sum,mx; for(int i=head[x];i;i=e[i].pre){ int v=e[i].v; if(v==from)continue;Dfs(v,x); mx=max(f[v][1],f[v][0]);sum=0; if(mx==f[v][1])sum+=g[v][1]; if(mx==f[v][0])sum+=g[v][0]; f[x][0]+=mx;g[x][0]*=sum; mx=f[v][0];sum=g[v][0]; f[x][1]+=mx;g[x][1]*=sum; }}int main(){ while(1){ cin>>n;if(n==0)break; cnt=0;num=0;r.clear(); memset(f,0,sizeof(f)); memset(g,0,sizeof(g)); memset(head,0,sizeof(head)); string u,v,root; cin>>root;r[root]=++cnt; for(int i=1;i<n;i++){ cin>>u>>v; if(r[u]==0)r[u]=++cnt; if(r[v]==0)r[v]=++cnt; Add(r[u],r[v]); Add(r[v],r[u]); } Dfs(r[root],0); int mx,sum=0; mx=max(f[r[root]][1],f[r[root]][0]); if(mx==f[r[root]][1])sum+=g[r[root]][1]; if(mx==f[r[root]][0])sum+=g[r[root]][0]; printf("%d ",mx); if(sum==1)printf("Yes\n"); else printf("No\n"); }}
树形dp练习
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。