题目传送门

题意:求一颗树中所有点对(a,b)的路径长度,路径长度按照模3之后的值进行分类,最后分别求每一类的和

分析:树形DP

\(dp[i][j]\) 表示以 i 为根的子树中,所有子节点到 i 的路径长度模3等于 j 的路径之和

\(c[i][j]\) 表示以 i 为根的子树中,所有子节点到 i 的路径长度模3等于 j 的点数

\(ok[i][j]\) 表示以 i 为根的子树中,是否有子节点到 i 的路径长度模3等于 j

每次只考虑所有经过根 x 的路径,并且路径的一个端点在 x 的一颗子树上,另一个端点在 x 的另一颗子树上。(可以想到其他所有情况都可以在考虑 x 的子树结点或者是x的祖先结点时被考虑到)

假设当前枚举到 x 的子节点 y,之前遍历的子节点已经使得三个数组更新。那么我们假设要计算的路径的起点在 y ,要计算的路径的终点在之前遍历过的子节点中。

计算答案贡献:

关于x-y的连边的贡献为

\(c[x][a] * c[y][b] * edge\)

关于起点到 y 的所有路径长度的贡献为

\(c[x][a] * dp[y][b]\)

关于x到终点的所有路径长度的贡献为

\(c[y][b] * dp[x][a]\)

最终边权所属分类为\((a+b+edge) \% 3\) 累加到答案即可

关于更新 x

用 y 来更新 x

\(dp[x][(a+edge)\%3] += dp[y][a] + edge * c[y][a]\)

\(ok[x][(a+edge)\%3] = true\)

\(c[x][(a+edge)\%3] += c[y][a]\)

当然点分治也可以做,但是复杂度就不是很优秀了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 10010;
const int M = 200010;
const ll mod = 1e9 + 7;
int head[N],ver[M],nxt[M],tot;
int x,y,n;
bool ok[N][3];
ll edge[M],z,dp[N][3],c[N][3];
ll ans[3];
void add(int x,int y,ll z){
ver[++tot] = y;edge[tot] = z;nxt[tot] = head[x];head[x] = tot;
}
void dfs(int x,int fa){
for(int i=head[x];i;i=nxt[i]){
int y = ver[i];
if(y == fa)continue;
dfs(y,x);
ll z = edge[i];
for(int j=0;j<3;j++){
for(int k=0;k<3;k++){
if(ok[x][j] && ok[y][k]){
ans[(j+k+z)%3] += (dp[x][j] * c[y][k]% mod + dp[y][k] * c[x][j] % mod) % mod;
ans[(j+k+z) % 3] += z * c[x][j] * c[y][k] % mod;
ans[(j+k+z)%3] %= mod;
}
}
}
for(int j=0;j<3;j++){
if(ok[y][j]){
dp[x][(j+z) % 3] += dp[y][j] + z * c[y][j] % mod;
dp[x][(j+z) % 3] %= mod;
c[x][(j+z)%3] += c[y][j];
ok[x][(j+z) % 3] = true;
}
}
}
}
int main(){
while(~scanf("%d",&n)){
ans[0] = ans[1] = ans[2] = 0;
tot = 0;
for(int i=1;i<=n;i++){
dp[i][0] = dp[i][1] = dp[i][2] = 0;
c[i][1] = c[i][2] = 0;
c[i][0] = 1;
ok[i][0] = true;
ok[i][1] = ok[i][2] = false;
head[i] = 0;
}
for(int i=1;i<n;i++){
scanf("%d%d%lld",&x,&y,&z);
x ++;
y ++;
add(x,y,z);
add(y,x,z);
}
dfs(1,0);
printf("%lld %lld %lld\n",ans[0] * 2 % mod,ans[1] * 2 % mod,ans[2] * 2 % mod);
}
return 0;
}

2019 沈阳网络赛 D Fish eating fruit ( 树形DP)的更多相关文章

  1. 2019icpc沈阳网络赛 D Fish eating fruit 树形dp

    题意 分别算一个树中所有简单路径长度模3为0,1,2的距离和乘2. 分析 记录两个数组, \(dp[i][k]\)为距i模3为k的子节点到i的距离和 \(f[i][k]\)为距i模3为k的子节点的个数 ...

  2. 2019 沈阳网络赛 Fish eating fruit

    这题看了三个月,终于过了,第一次看的时候没学树形DP,想用点分治但是不会 后来学了二次扫描,就有点想法了.... 这东西也真就玄学了吧... #include<iostream> #inc ...

  3. 2019沈阳网络赛B.Dudu's maze

    https://www.cnblogs.com/31415926535x/p/11520088.html 啊,,不在状态啊,,自闭一下午,,都错题,,然后背锅,,,明明这个简单的题,,, 这题题面不容 ...

  4. [2019沈阳网络赛D题]Dawn-K's water(点分治)

    题目链接 题意为求出树上任意点对的距离对3取余的和. 比赛上听到题意就知道是点分治了,但是越写越不对劲,交之前就觉得会T,果不其然T了.修修改改结果队友写了发dp直接就过了Orz. 赛后想了想维护的东 ...

  5. 【2019沈阳网络赛】G、Special necklace——自闭的物理题

    这道题让我差点怀疑自己高考没考过物理 题意中 he measures the resistance of any two endpoints of it, the resistance values ...

  6. 2019上海网络赛 F. Rhyme scheme 普通dp

    Rhyme scheme Problem Describe A rhyme scheme is the pattern of rhymes at the end of each line of a p ...

  7. 2019 上海网络赛 F Rhyme scheme (字典树DP)

    题目:https://nanti.jisuanke.com/t/41414 题意:求长度为n的第k个bell number  ,  就是第i位的选取范围在 1-(i-1)位的最大值 +1,第一位固定为 ...

  8. hdu6446 网络赛 Tree and Permutation(树形dp求任意两点距离之和)题解

    题意:有一棵n个点的树,点之间用无向边相连.现把这棵树对应一个序列,这个序列任意两点的距离为这两点在树上的距离,显然,这样的序列有n!个,加入这是第i个序列,那么这个序列所提供的贡献值为:第一个点到其 ...

  9. 2019沈阳网赛树形dp

    https://nanti.jisuanke.com/t/41403 2019沈阳网络赛D题 树形dp.一棵树,求任意两个点的距离之和.u-v和v-u算两次.两点之间的距离分为三类,模3等于0,1,2 ...

随机推荐

  1. 【详细】Python基础(一)

    @ 目录 前言 1. Python环境的搭建 1.1 python解释器的安装 1.2 pycharm的安装 2. Python基础语法 2.1 基本语法 2.2 数据类型 2.3 标识符与关键字 2 ...

  2. 【对线面试官】Java 反射&&动态代理

    // 抽象类,定义泛型<T> public abstract class BaseDao<T> { public BaseDao(){ Class clazz = this.g ...

  3. 【SpringBoot1.x】SpringBoot1.x Web 开发

    SpringBoot1.x Web 开发 文章源码 简介 SpringBoot 非常适合 Web 应用程序开发.可以使用嵌入式 Tomcat,Jetty 或 Undertow 轻松创建独立的 HTTP ...

  4. 剑指offer 面试题9:用两个栈实现队列

    题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 使用栈实现队列的下列操作:push(x) -- 将一个元素放入队列的尾部.pop() -- 从队列首部移 ...

  5. linux下的文件类型

    在Linux中一切设备皆文件,首先来看一下Linux下的文件都有哪些分类,也就是文件类型 文件类型:普通文件(包括shell脚本,文档,音频,视频).目录文件.设备文件(又细分为字符设备文件和块设备文 ...

  6. Deep Learn I'm back.

    Intorduction: 时隔好几个月,我准备重新进入Deep Learning 的领域.昨天和老师聊了很多,之前觉得我做的工作就是排列组合,在水论文,灌水.但老师却说:这也是为将来的研究打基础. ...

  7. Tomcat-8 安装和配置

    JDK 安装: # 选择版本: yum list all | grep jdk # 安装openjdk-1.8.0: yum install java-1.8.0-openjdk.x86_64 -y ...

  8. redis持久化怎么选?成年人从来不做选择...

    前言 面试官:你知道 redis 是的怎么做持久化的吗? 我:我知道 redis 有两种方式,一种是 RDB,一种是 AOF. 面试官:那这两种方式具体是怎么做的,它们的区别是什么,生产环境中到底应该 ...

  9. Burp suite的系列介绍 (1)

    前言 为了进行Web安全方面的学习,Burp suite是必备的工具之一,我们将会从多个模块进行逐步的学习. Burp suite的应用场景 1.HTTP服务端接口测试. 2.HTTP客户端和HTTP ...

  10. sentinel-实战

    sentinel-实战笔记 什么是Sentinel Sentinel是阿里开源的项目,提供了流量控制.熔断降级.系统负载保护等多个维度来保障服务之间的稳定性. Sentinel主要特性: 获取Sent ...