【洛谷】P5024 保卫王国
作者:互联网
前言
传送门
很多人写了题解了,我就懒得写了,推荐一篇博客
那就分享一下我的理解吧(说得好像有人看一样
对于每个点都只有选与不选两种情况,所以直接用倍增预处理出来两种情况的子树之内,子树之外的最值,最终答案以拼凑的方式得出
如果这个题要修改权值的话就真的只能用动态dp了(好像还有那个什么全局平衡树
我真的觉得去年出题人只是想出一个倍增,结果被动态dp干了(Ark:出题人真的只是想出一个动态dp
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100005; const long long inf=1ll<<60; long long f[maxn][30],g[maxn][30],F[maxn][30][2][2];char ch[10]; int n,m,ecnt,v[maxn<<1],nx[maxn<<1],dep[maxn],info[maxn],fa[maxn][30]; void add(int u1,int v1){nx[++ecnt]=info[u1];info[u1]=ecnt;v[ecnt]=v1;} void dfs1(int x,int fath) { dep[x]=dep[fa[x][0]=fath]+1; for(int i=info[x];i;i=nx[i])if(v[i]!=fath) dfs1(v[i],x),f[x][0]+=f[v[i]][1],f[x][1]+=min(f[v[i]][0],f[v[i]][1]); } void dfs2(int x) { for(int i=info[x];i;i=nx[i])if(v[i]!=fa[x][0]) g[v[i]][0]=g[x][1]+f[x][1]-min(f[v[i]][0],f[v[i]][1]), g[v[i]][1]=min(g[v[i]][0],g[x][0]+f[x][0]-f[v[i]][1]),dfs2(v[i]); } long long solve(int x,int a,int y,int b) { if(dep[x]<dep[y])swap(x,y),swap(a,b); long long tx[2]={inf,inf},ty[2]={inf,inf},nwx[2],nwy[2]; tx[a]=f[x][a];ty[b]=f[y][b]; for(int i=25;i>=0;i--)if((dep[x]-dep[y])&(1<<i)) { nwx[0]=nwx[1]=inf; for(int u=0;u<=1;u++)for(int v=0;v<=1;v++) nwx[u]=min(nwx[u],tx[v]+F[x][i][v][u]); tx[0]=nwx[0],tx[1]=nwx[1];x=fa[x][i]; } if(x==y)return nwx[b]+g[y][b]; for(int i=25;i>=0;i--)if(fa[x][i]!=fa[y][i]) { nwx[0]=nwx[1]=nwy[0]=nwy[1]=inf; for(int u=0;u<=1;u++)for(int v=0;v<=1;v++) nwx[u]=min(nwx[u],tx[v]+F[x][i][v][u]),nwy[u]=min(nwy[u],ty[v]+F[y][i][v][u]); tx[0]=nwx[0],tx[1]=nwx[1];x=fa[x][i];ty[0]=nwy[0],ty[1]=nwy[1];y=fa[y][i]; } int lca=fa[x][0]=fa[y][0]; long long ret1=g[lca][0]+f[lca][0]-f[x][1]-f[y][1]+tx[1]+ty[1], ret2=g[lca][1]+f[lca][1]-min(f[x][0],f[x][1])-min(f[y][0],f[y][1])+min(tx[0],tx[1])+min(ty[0],ty[1]); return min(ret1,ret2); } int main() { scanf("%d%d%s",&n,&m,ch+1);for(int i=1;i<=n;i++)scanf("%lld",&f[i][1]); for(int i=1,u1,v1;i<n;i++)scanf("%d%d",&u1,&v1),add(u1,v1),add(v1,u1); dfs1(1,0);dfs2(1);memset(F,0x3f,sizeof F); for(int i=1;i<=n;i++) F[i][0][1][1]=f[fa[i][0]][1]-min(f[i][0],f[i][1]),F[i][0][0][0]=inf, F[i][0][0][1]=f[fa[i][0]][1]-min(f[i][0],f[i][1]),F[i][0][1][0]=f[fa[i][0]][0]-f[i][1]; for(int k=1;k<=25;k++)for(int i=1;i<=n;fa[i][k]=fa[fa[i][k-1]][k-1],i++) for(int u=0;u<=1;u++)for(int v=0;v<=1;v++)for(int w=0;w<=1;w++) F[i][k][u][v]=min(F[i][k][u][v],F[i][k-1][u][w]+F[fa[i][k-1]][k-1][w][v]); for(int i=1,a,b,x,y;i<=m;i++) { scanf("%d%d%d%d",&x,&a,&y,&b); if(a==0&&b==0&&(fa[x][0]==y||fa[y][0]==x))puts("-1"); else printf("%lld\n",solve(x,a,y,b)); } }
标签:洛谷,nwx,nwy,long,保卫,inf,include,P5024,dp 来源: https://www.cnblogs.com/firecrazy/p/11756163.html