【51nod 1325】两棵树的问题
2016-12-28 12:38
337 查看
Description
有两颗各含N个点的无根树,每棵树中点分别被编号为0,1,2,….,N-1;注意两棵树并不保证同构。另外给一个N长的整数数组Score[],记录N个编号的得分,Score中的每个元素可正可负。
问题的任务是寻找 集合{0,1,2,3,4,…,N-1}的一个最优子集subset,要求满足以下条件:
1)在第一棵树中,subset中包含的编号对应的点能构成一个连通的子图;即去掉这棵树中所有subset中不包含的点后,剩下的点依然是一棵连通的树。
2)在第二棵树中,subset中包含的编号对应的点也能构成一个连通的子图;
3)使subset包含编号的总得分尽可能的大;即SUM{ Score[i] | i∈subset }能取到尽可能大的值。
输出这个subset包含编号的总分的最大值。
N<=50
Solution
先枚举一个根,使得根必须选,把问题转化成了在两棵树中从根上开始选k个使得权值最大,除了根以外,每个点如果要选,就一定要选它在两棵树中的父亲,
咦,有依赖关系的带权图???
好,最大权闭合子图走起!
复杂度:O(n4)
Code
#include <iostream> #include <cstdio> #include <cstdlib> #define fo(i,a,b) for(int i=a;i<=b;i++) #define efo(i,q) for(int i=A[K][q];i;i=B[i][0]) using namespace std; const int N=55,INF=1047483640; int read(int &n) { char ch=' ';int q=0,w=1; for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar()); if(ch=='-')w=-1,ch=getchar(); for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n; } int K; int n,m,ans,ans1,S,T; int b ; int B[N*N*N][3],B0=1,A[3] ; int h ,hv ; void link(int k,int q,int w,int e,int e1) { B[++B0][0]=A[k][q],A[k][q]=B0,B[B0][1]=w,B[B0][2]=e; B[++B0][0]=A[k][w],A[k][w]=B0,B[B0][1]=q,B[B0][2]=e1; } void dfs(int q,int fa) { if(fa)link(0,q,fa,INF,0); efo(i,q)if(B[i][1]!=fa) dfs(B[i][1],q); } int aug(int q,int v) { if(q==T)return v; int mi=T+2; efo(i,q)if(B[i][2]) { if(h[q]==h[B[i][1]]+1) { int t=aug(B[i][1],min(v,B[i][2])); if(t) { B[i][2]-=t; B[i^1][2]+=t; return t; } } if(h[S]>T+1)return 0; mi=min(mi,h[B[i][1]]); } if(!(--hv[h[q]]))h[S]=T+2; hv[h[q]=mi+1]++; return 0; } int main() { int q,w; read(n); S=0;T=n+1; fo(i,1,n)ans1+=read(b[i])>0?b[i]:0; fo(i,1,n-1)read(q),read(w),link(1,++q,++w,0,0); fo(i,1,n-1)read(q),read(w),link(2,++q,++w,0,0); fo(i,1,n)if(b[i]>0) { int Q=B0; fo(j,0,n+2)A[0][j]=0,h[j]=0,hv[j]=0; fo(j,1,n)if(b[j]>0)link(0,S,j,b[j],0); else link(0,j,T,-b[j],0); K=1,dfs(i,0); K=2,dfs(i,0); q=K=0;hv[0]=T+1; while(h[S]<=T+1)q+=aug(S,INF); ans=max(ans,ans1-q); B0=Q; } printf("%d\n",ans); return 0; }
相关文章推荐
- 51nod 1325 两棵树的问题 最大权闭合子图
- 51nod 1084 更难的矩阵取数问题(DP)
- 51nod 1087 1 10 100 1000(数学问题)
- 51nod 1394:差和问题
- 1083 矩阵取数问题 分类: 51nod 2015-07-20 22:05 9人阅读 评
- 51Nod 1499 进制转化问题。
- 1083 矩阵取数问题 分类: 51nod 2015-07-20 22:05 9人阅读 评
- 51nod 数塔取数问题 —— 动态规划
- 51Nod 1002 数塔取数问题
- 51nod最大子段和问题
- office2007安装过程中出错错误1325 短文件名"Favorites"无效 问题的解决办法
- 51nod 活动安排问题 (贪心)
- 51nod 1038 矩阵取数问题 (DP)
- 51nod 差和问题(树状数组+离散化 (Java))
- 51nod 活动安排问题之二 (贪心+stl)
- 51nod 1428 活动安排问题 (贪心+优先队列)
- 51nod 1243 排船的问题(锻炼思维的好题)
- 51nod 多重背包问题 (dp)
- 51nod贪心例子活动安排问题二
- 51nod 1434 数论区间LCM问题