zoukankan      html  css  js  c++  java
  • CF543D Road Improvement(换根dp)

    传送门

    唔感觉这几天换根用的好多啊,所以换根dp还是打一下好了。(虽然觉得一道题不大够的亚子)

    所以大佬们有什么换根好题可以推荐一下的嗷!

    这道题因为对于每一个点都要统计答案,所以要换根。

    我们先考虑对于一个根我们怎么求出答案。

    因为每个点到根的路径上只能有一条不良道路。

    设f[i]为以i为根的子树内分配不良道路的方案数。

    现在就有两种情况:

    1. i 到son那条边是不良道路,那么以 i 为根的子树内都不会是不良道路。

    2.i 到son那条边不是不良道路,那么加上f[son]。

    所以答案为f[son]+1的累乘。

    接下来考虑换根:

    发现当根从 i 变成 j 的某个孩子时,变化的只有f[i]和f[j]。

    f[i]会除掉关于 j 的贡献,f[j]会乘上 i 的贡献。

    因为除的时候不一定会有逆元,这里我们使用前缀积和后缀积的方式处理。

    具体看代码吧。

    #include<bits/stdc++.h>
    #define N 200003
    #define LL long long
    #define INF 2100000000
    #define mod 1000000007
    using namespace std;
    int read()
    {
        int x=0,f=1;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    void print(int x)
    {
        if(x<0)putchar('-'),x=-x;
        if(x>9)print(x/10);
        putchar(x%10+'0');
    }
    struct EDGE{
        int nextt,to;
    }w[N*2];
    int tot=0;
    int head[N];
    void add(int a,int b)
    {
        tot++;
        w[tot].nextt=head[a];
        w[tot].to=b;
        head[a]=tot;
    }
    int n;
    LL f[N],ans[N];
    vector<LL>qzj[N],hzj[N];
    void dfs1(int x,int fa)
    {
        f[x]=1;
        for(int i=head[x];i;i=w[i].nextt)
        {
            int v=w[i].to;
            if(v==fa)continue;
            dfs1(v,x);
            f[x]=(f[x]*(f[v]+1)%mod)%mod;
        }
    }
    void dfs2(int x,int fa)//换根 
    {
        ans[x]=1;
        for(int i=head[x];i;i=w[i].nextt)
        {
            int v=w[i].to;
            ans[x]=(ans[x]*(f[v]+1)%mod)%mod;
            if(v!=fa)
            {
                qzj[x].push_back(f[v]+1);
                hzj[x].push_back(f[v]+1);
            }
        }
        for(int i=1;i<qzj[x].size();++i)qzj[x][i]=qzj[x][i]*qzj[x][i-1]%mod;
        for(int i=hzj[x].size()-2;i>=0;--i)hzj[x][i]=hzj[x][i]*hzj[x][i+1]%mod;
        int cnt=0;
        for(int i=head[x];i;i=w[i].nextt)
        {
            int v=w[i].to;
            if(v==fa)continue;
             f[x]=fa?(f[fa]+1):1;
            if(cnt>0)f[x]=f[x]*qzj[x][cnt-1]%mod;
            if(cnt<hzj[x].size()-1)f[x]=f[x]*hzj[x][cnt+1]%mod;
            dfs2(v,x);cnt++;
        }
    }
    int main()
    {
        n=read();
        for(int i=2;i<=n;++i)
        {
            int x=read();
            add(x,i);add(i,x);
        }
        dfs1(1,0);
        dfs2(1,0);
        for(int i=1;i<=n;++i)printf("%lld ",ans[i]);
    }
    /*
    */
    View Code
  • 相关阅读:
    即将到来的Android N,将具备这些新特性
    刚挣钱的程序猿同学该怎样花钱?
    Swift函数
    MVC
    css3硬件加速
    node+mongoDB+express项目需求解释
    柯里化
    web安全
    缓存机制详解
    nodejs --- crypto实现加密(转)
  • 原文地址:https://www.cnblogs.com/yyys-/p/11845001.html
Copyright © 2011-2022 走看看