题目传送门

题意:求一颗树中所有点对(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. Kafka 探险 - 架构简介

    Kafka 探险 - 架构简介 这个 Kafka 的专题,我会从系统整体架构,设计到代码落地.和大家一起杠源码,学技巧,涨知识.希望大家持续关注一起见证成长! 我相信:技术的道路,十年如一日!十年磨一 ...

  2. 动态方法拦截(AOP)的N种解决方案

    AOP的本质是方法拦截(将针对目标方法调用劫持下来,进而执行执行的操作),置于方法拦截的实现方案,不外乎两种代码注入类型,即编译时的静态注入和运行时的动态注入,本篇文章列出了几种常用的动态注入方案.这 ...

  3. react项目中实现搜索关键字呈现高亮状态(一)

    最近有个需求,在一个react项目中,实现搜索关键字呈现高亮状态.这个在普通的html文件中还好操作些,在react项目中有点懵逼了,因为react项目中很少操作dom,有点无从下手.但最后还是实现了 ...

  4. 【Nginx学习笔记】-初识Nginx

    Nginx 目录 Nginx Nginx 特点 Nginx 基本功能 Nginx 使用场景 Nginx 安装/卸载 Docker 方式运行 Ubuntu上安装 卸载Nginx Nginx 命令 Ngi ...

  5. 剑指offer 面试题6:从尾到头打印链表

    题目描述 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. 编程思想 从前往后遍历,将值存入栈中,然后打印栈中内容即可. 编程实现 /** * struct ListNode { * ...

  6. Python列表推导式玩法

    前言 列表做为python的基础,是必须学习的语法之一.一些基础的之前已经是反复温习和使用了,今天我们来学习它的进阶版-->列表推导式. 列表推导式: 优点:是将所有的值一次性加载到内存中,相比 ...

  7. redis之集群二:哨兵

    回顾 上一篇介绍了Redis的主从集群模式,这个集群模式配置很简单,只需要在Slave的节点上进行配置,Master主节点的配置不需要做任何更改.但是,我们发现这种集群模式当主节点宕机,主从无法自动切 ...

  8. iostat的输出

    第一行显示的时子系统启动以来的平均值,接下来的报告显示了增量的平均值,每个设备一行 Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   ...

  9. ctfhub技能树—web前置技能—http协议—响应包源代码

    打开靶机环境 查看网页是一个贪吃蛇小游戏 根据提示查看源码 发现flag 至此HTTP协议结束

  10. 你这样用过DO循环吗?

    DATA: BEGIN OF text,        word1(4) TYPE c VALUE 'This',        word2(4) TYPE c VALUE 'is',         ...