您的位置:首页 > 其它

【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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: