CF543D Road Improvement(换根dp)
时间:2019-11-12
本文章向大家介绍CF543D Road Improvement(换根dp),主要包括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]); } /* */
原文地址:https://www.cnblogs.com/yyys-/p/11845001.html
- 如何求最小三元组距离
- 如何将Pastebin上的信息应用于安全分析和威胁情报领域
- Optionsbleed 漏洞泄露 Apache Server 的内存信息
- 对两个有序数组进行合并
- No.016 3Sum Closest
- Java中实现解码字符串的方法,实用代码
- PDF.NET SOD 开源框架红包派送活动 && 新手快速入门指引
- No.015 3Sum
- Java 8新特性——提供了一种可以看作多重继承的默认方法
- WebSocket 学习笔记--IE,IOS,Android等设备的兼容性问题与代码实现
- 关于Shell你想知道的都在这儿
- Java中使用线程时,请不要忘记Spring TaskExecutor组件
- 常见.NET功能代码汇总
- 如何通过追踪代码自动发现网站之间的“关联”
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法