首页 > 其他 > 详细

CF543D Road Improvement(换根dp)

时间:2019-11-12 22:25:08      阅读:85      评论:0      收藏:0      [点我收藏+]

传送门

唔感觉这几天换根用的好多啊,所以换根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

 

CF543D Road Improvement(换根dp)

原文:https://www.cnblogs.com/yyys-/p/11845001.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!