保卫王国
w的定义类似于上图。
并且上图是其中一类特殊情况。
剩余状态的例图,主义这是 \(LCA:p\) 不选的情况,选的情况也是类似的。
减去 \(f_v\) 就是 在原有的 \(f_u\) 中去掉子树 \(v\) 的贡献,也可用新的 \(s\) 替换。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while
typedef long long ll;
const int N=100010,M=17,MM=2*N;
ll f[N][2],g[N][2],w[N][M][2][2];
int n,m,fa[N][M],p[N],dep[N];
int h[N],e[MM],ne[MM],idx;//don't forget memset h!
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs_f(int x,int fa){
f[x][1]=p[x];
Ed{
int j=e[i];
if(j==fa)continue;
dfs_f(j,x);
f[x][0]+=f[j][1];
f[x][1]+=min(f[j][0],f[j][1]);
}
}
void dfs_g(int x,int fa){
Ed{
int j=e[i];
if(j==fa)continue;
g[j][0]=f[x][1]+g[x][1]-min(f[j][0],f[j][1]);
g[j][1]=min(g[j][0],f[x][0]+g[x][0]-f[j][1]);
dfs_g(j,x);
}
}
void dfs_fa(int x,int fat){
Ed{
int j=e[i];
if(j==fat)continue;
dep[j]=dep[x]+1;
fa[j][0]=x;
Ls(k, 1, M)fa[j][k]=fa[fa[j][k-1]][k-1];
dfs_fa(j,x);
}
}
void dfs_w(int x,int fat){
Ed{
int j=e[i];
if(j==fat)continue;
w[j][0][0][1]=w[j][0][1][1]=f[x][1]-min(f[j][0],f[j][1]);
w[j][0][1][0]=f[x][0]-f[j][1];
Ls(k, 1, M)
L(x, 2)
L(y, 2)
L(z, 2)w[j][k][x][y]=min(w[j][k][x][y],w[j][k-1][x][z]+w[fa[j][k-1]][k-1][z][y]);
dfs_w(j,x);
}
}
ll calc(int a,int x,int b,int y){
if(dep[a]<dep[b])swap(a,b),swap(x,y);
if(!x&&!y&&fa[a][0]==b)return -1;
ll na[2],nb[2],sa[2],sb[2];
memset(sa,0x3f,sizeof sa);
memset(sb,0x3f,sizeof sb);
sa[x]=f[a][x],sb[y]=f[b][y];
Re(i, M-1, 0)
if(dep[fa[a][i]]>=dep[b]){
memset(na,0x3f,sizeof na);
L(x, 2)
L(y, 2)na[y]=min(na[y],sa[x]+w[a][i][x][y]);
memcpy(sa,na,sizeof sa);
a=fa[a][i];
}
if(a==b)return g[b][y]+sa[y];
Re(i, M-1, 0)
if(fa[a][i]!=fa[b][i]){
memset(na,0x3f,sizeof na);
memset(nb,0x3f,sizeof nb);
L(x, 2)
L(y, 2)
na[y]=min(na[y],sa[x]+w[a][i][x][y]),
nb[y]=min(nb[y],sb[x]+w[b][i][x][y]);
memcpy(sa,na,sizeof sa);
memcpy(sb,nb,sizeof sb);
a=fa[a][i],b=fa[b][i];
}
int lca=fa[a][0];
ll res0=f[lca][0]+g[lca][0]-f[a][1]-f[b][1]+sa[1]+sb[1];
ll res1=f[lca][1]+g[lca][1]-min(f[a][1],f[a][0])-min(f[b][1],f[b][0])+min(sa[0],sa[1])+min(sb[0],sb[1]);
return min(res0,res1);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
scanf("%d%d%*s",&n,&m);
memset(h,-1,n*4+4);
E(i, n)scanf("%d",p+i);
E(i, n-1){
int a,b;
scanf("%d%d",&a,&b);
add(a,b),add(b,a);
}
dfs_f(1,-1);
dfs_g(1,-1);
dep[1]=1;
dfs_fa(1,-1);
memset(w,0x3f,sizeof w);
dfs_w(1,-1);
W(m){
int a,x,b,y;
scanf("%d%d%d%d",&a,&x,&b,&y);
printf("%lld\n",calc(a,x,b,y));
}
return 0;
}
标签:min,int,na,fa,保卫,sa,sizeof,王国
From: https://www.cnblogs.com/wscqwq/p/17715479.html