Description
Solution
观察数据范围,容易想到这是一个简单的线性规划模型。
每一个点可以看做变量xi∈{0,1}x_i\in\{0,1\}xi∈{0,1}
然后每个限制对应一个等于号的方程,最后要求目标函数最大。
但是直接跑线性规划的单纯形算法会TLE。
我们观察这题的性质,由于保证了整棵树都会有限制,那么如果我们在两棵树上分别差分,即每个点只对应包含它的最小的子树的限制,外面套的就减去。
这样每个点就在两棵树上恰好分别对应一个限制。
这样就容易建图了,对于两个数中的每一个限制都建一个点,一个原来的点看做一条连接两个限制的边,容量为1,费用为w[i]
源点相应向第一棵树限制链容量为限制的点数,费用为0。
第二棵树的限制相应向汇点连边。
跑最大费用最大流即可,如果源点到第一棵树的限制的边以及第二棵树的限制到汇点的边全部满流则合法,否则就是-1
实现上有一点小细节,就是直接将树上的点看做边可能会造成重边比较麻烦,我们可以将每个树点对应的边拆成两条,中间新建一个点,这样就没有重边了。
Code
#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 505
using namespace std;
int n,sx,sy,fs[N],nt[2*N],dt[2*N],fi[N],nx[2*N],dx[2*N],m2,m1,ans;
int pr[N],f[2*N][2*N],fr[N][2],lw[N*2],a1[2*N][2*N],cs[2*N][2*N],dis[2*N],st,ed,d[N*N],ls[2*N],ds[2*N];
bool bz[2*N];
void link(int x,int y)
{
nt[++m1]=fs[x];
dt[fs[x]=m1]=y;
}
void lk(int x,int y)
{
nx[++m2]=fi[x];
dx[fi[x]=m2]=y;
}
void dfs(int k,int fa)
{
if(fr[k][0]&&fa!=0) lw[fr[fa][0]]-=lw[fr[k][0]];
else if(fa!=0) fr[k][0]=fr[fa][0];
for(int i=fs[k];i;i=nt[i])
{
int p=dt[i];
if(p!=fa) dfs(p,k);
}
}
void dfs2(int k,int fa)
{
if(fr[k][1]&&fa!=0) lw[fr[fa][1]]-=lw[fr[k][1]];
else if(fa!=0) fr[k][1]=fr[fa][1];
for(int i=fi[k];i;i=nx[i])
{
int p=dx[i];
if(p!=fa) dfs2(p,k);
}
}
void hb(int x,int y,int l,int c)
{
cs[x][y]=c;
cs[y][x]=-c;
a1[x][++a1[x][0]]=y;
a1[y][++a1[y][0]]=x;
f[x][y]=l,f[y][x]=0;
}
bool spfa()
{
memset(dis,107,sizeof(dis));
memset(bz,0,sizeof(bz));
int l=0,r=1;
d[1]=st,bz[st]=1;
dis[st]=0;
while(l<r)
{
int k=d[++l];
fo(i,1,a1[k][0])
{
int p=a1[k][i];
if(f[k][p]&&dis[k]+cs[k][p]<dis[p])
{
dis[p]=dis[k]+cs[k][p];
ls[p]=k;
if(!bz[p]) bz[p]=1,d[++r]=p;
}
}
bz[k]=0;
}
return (dis[ed]<1e9);
}
int main()
{
cin>>n>>sx>>sy;
fo(i,1,n) scanf("%d",&pr[i]);
fo(i,1,n-1)
{
int x,y;
scanf("%d%d",&x,&y);
link(x,y),link(y,x);
}
fo(i,1,n-1)
{
int x,y;
scanf("%d%d",&x,&y);
lk(x,y),lk(y,x);
}
int q,q1;
cin>>q;
fo(i,1,q)
{
int x,y;
scanf("%d%d",&x,&y);
fr[x][0]=i,lw[i]=y;
}
dfs(sx,0);
cin>>q1;
fo(i,1,q1)
{
int x,y;
scanf("%d%d",&x,&y);
fr[x][1]=i+q,lw[i+q]=y;
}
dfs2(sy,0);
st=q+q1+1,ed=st+1;
fo(i,1,q)
{
if(lw[i]<0) {printf("-1\n");return 0;}
hb(st,i,lw[i],0);
}
fo(i,1,q1)
{
if(lw[i+q]<0) {printf("-1\n");return 0;}
hb(i+q,ed,lw[i+q],0);
}
fo(i,1,n)
{
hb(fr[i][0],i+q+q1+2,1,-pr[i]);
hb(i+q+q1+2,fr[i][1],1,0);
}
int ans=0;
while(spfa())
{
int k=ed,s=1802201963;
ds[0]=0;
while(k!=st) ds[++ds[0]]=k,s=min(s,f[ls[k]][k]),k=ls[k];
ds[++ds[0]]=st;
fod(i,ds[0],2)
{
f[ds[i]][ds[i-1]]-=s;
f[ds[i-1]][ds[i]]+=s;
}
ans+=dis[ed]*s;
}
fo(i,1,q) if(f[st][i]>0) {printf("-1\n");return 0;}
fo(i,1,q1) if(f[i+q][ed]>0) {printf("-1\n");return 0;}
printf("%d\n",-ans);
}