zoukankan      html  css  js  c++  java
  • 【洛谷】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
    ",solve(x,a,y,b));
        }
    }
  • 相关阅读:
    菜根谭#219
    菜根谭#218
    菜根谭#217
    菜根谭#216
    有了OpenMP,MPI,为什么还要MapReduce? (转载)
    人生就是一场战略
    SDAccel 开发环境
    各种加速卡 异构计算
    Nvidia Tesla (GPGPU)系列发展流程
    Nvidia 架构发展
  • 原文地址:https://www.cnblogs.com/firecrazy/p/11756163.html
Copyright © 2011-2022 走看看