https://nanti.jisuanke.com/t/41403

2019沈阳网络赛D题

树形dp。一棵树,求任意两个点的距离之和。u-v和v-u算两次。两点之间的距离分为三类,模3等于0,1,2三类,最后输出这三类的总和。

第一种方法。直接累加。遍历到一个点的时候。先计算答案。答案加上所有已经遍历过得点到他的距离之和。同时该点也要加上这个值,同时要加上数量。每次先搜到底统计往下遍历的值,然后回溯的时候统计

回溯的值。因为每次只计算了之前的点到他的距离之和,所以最后的结果要乘以2,因为u-v与v-u算两次。

每次加的时候先计算当前点前一个点到他的距离,及0+该边的边权。然后在按0,1,2来累加,如果为零表示没有,就不累加。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e4 + ;
const int mod = 1e9 + ;
typedef pair<int, ll> pii;
int n;
vector<pii> g[N];
ll ans[];//结果数组
struct Node {
ll valup[];//递归回溯的时候
ll valdown[];//递归往下的时候
ll cntdown[], cntup[];//递归往下与回溯的点数量。
} node[N]; void dfs(int u, int f) {
int len = g[u].size();
for(int i = ; i < len; i++) {
int v = g[u][i].first;
ll w = g[u][i].second;
if(v == f) continue;
node[v].valdown[w%] = (node[v].valdown[w%] + w) % mod;
node[v].cntdown[w%] = (node[v].cntdown[w%] + ) % mod;
ans[w%] = (ans[w%] + w) % mod;
for(int j = ; j < ; j++) {
ll ww = (node[u].valdown[j] + node[u].valup[j]) % mod;
ll cnt = (node[u].cntdown[j] + node[u].cntup[j]) % mod;
if(ww == ) continue;
ll mo = (j + w) % ;
node[v].valdown[mo] = (node[v].valdown[mo] + ww) % mod;
node[v].valdown[mo] = (node[v].valdown[mo] + w * cnt) % mod;
node[v].cntdown[mo] = (node[v].cntdown[mo] + cnt) % mod;
ans[mo] = (ans[mo] + ww) % mod;
ans[mo] = (ans[mo] + w * cnt) % mod;
}
dfs(v, u);
node[u].valup[w%] = (node[u].valup[w%] + w) % mod;
node[u].cntup[w%] = (node[u].cntup[w%] + ) % mod;
for(int j = ; j < ; j++) {
ll ww = node[v].valup[j];
ll cnt = node[v].cntup[j];
if(ww == ) continue;
ll mo = (j + w) % ;
node[u].valup[mo] = (node[u].valup[mo] + ww) % mod;
node[u].valup[mo] = (node[u].valup[mo] + w * cnt) % mod;
node[u].cntup[mo] = (node[u].cntup[mo] + cnt) % mod;
}
}
} int main() {
while(~scanf("%d", &n)) {
int u, v;
ll w;
ans[] = ans[] = ans[] = ;
for(int i = ; i < n; i++) {
g[i].clear();
for(int j = ; j < ; j++) node[i].valup[j] = node[i].valdown[j] = node[i].cntdown[j] = node[i].cntup[j] = ;
}
for(int i = ; i < n; i++) {
scanf("%d%d%lld", &u, &v, &w);
g[u].push_back(pii(v, w));
g[v].push_back(pii(u, w));
}
dfs(, -);
for(int i = ; i < ; i++) {
printf("%lld%c", (ans[i] * ) % mod, i == ? '\n' : ' ');
}
}
return ;
}

算贡献的方法。

#include <stdio.h>
#include <string.h>
using namespace std;
#define LL long long
const int N=;
const LL MOD = 1e9 + ; int n,root;
int nex[N],tot,fir[N],to[N],len[N];
LL f[N][],g[N][],num[N][];
void build(int x,int y,int z)
{
nex[++tot]=fir[x];
fir[x]=tot;
to[tot]=y;
len[tot]=z;
} void mo(LL &x) {
x %= MOD;
if(x < ) x += MOD;
} void dfs(int x,int fa)
{
num[x][]++;
for(int i=fir[x];i;i=nex[i])
{
int y=to[i];
if(y==fa)continue;
dfs(y,x);
for(int j=;j<;++j){
g[x][(j+len[i])%]+=(num[y][j]*len[i]+g[y][j]) % MOD;
num[x][(j+len[i])%]+=num[y][j];
f[x][j] += f[y][j]; mo(num[x][(j+len[i])%]);
mo(g[x][(j + len[i]) % ]);
mo(f[x][j]);
}
}
for(int i=;i<;i++)
{
f[x][i]+=g[x][i];
mo(f[x][i]);
}
for(int i=fir[x];i;i=nex[i])
{
int y=to[i];
if(y==fa)continue;
for(int j=;j<;++j) {
int ind = (j-len[i])%;
if(ind < ) ind += ;
for(int k=;k<;++k) {
f[x][(j+k+len[i])%]+=len[i]*(num[x][j]-num[y][ind]) % MOD *num[y][k] % MOD ;
f[x][(j+k+len[i])%]+=(g[x][j] - g[y][ind] - num[y][ind] * len[i]) % MOD *num[y][k] % MOD ;
f[x][(j+k+len[i])%]+=(num[x][j]-num[y][ind])*g[y][k] % MOD;
mo(f[x][(j+k+len[i])%]);
}
}
}
} int main()
{
// freopen("a.in","r",stdin);
int n;
while (~scanf("%d",&n)) {
tot=;
memset(fir,,sizeof(fir));
memset(f,,sizeof(f));
memset(g,,sizeof(g));
memset(num,,sizeof(num));
for (int i = ;i < n;i++) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
x++;y++;
build(x,y,z);
build(y,x,z);
}
dfs(,);
printf("%lld %lld %lld\n",f[][],f[][],f[][]); } return ;
} /**
3
0 1 2
0 2 3
*/

2019沈阳网赛树形dp的更多相关文章

  1. HDU 6201 2017沈阳网络赛 树形DP或者SPFA最长路

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6201 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过 ...

  2. 2019 沈阳网络赛 D Fish eating fruit ( 树形DP)

    题目传送门 题意:求一颗树中所有点对(a,b)的路径长度,路径长度按照模3之后的值进行分类,最后分别求每一类的和 分析:树形DP \(dp[i][j]\) 表示以 i 为根的子树中,所有子节点到 i ...

  3. 2019 沈阳网络赛 Fish eating fruit

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

  4. 2015年沈阳网赛 Jesus Is Here(DP中的计数问题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5459 题目描述:给定一个递推得来的字符串,问字符串中不同cff之间的距离之和, 递推规则: s1=c; ...

  5. hdu 4274 2012长春赛区网络赛 树形dp ***

    设定每个节点的上限和下限,之后向上更新,判断是否出现矛盾 #include<cstdio> #include<iostream> #include<algorithm&g ...

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

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

  7. hdu5461 Largest Point(沈阳网赛)

    Largest Point Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total ...

  8. hdu 5455 (2015沈阳网赛 简单题) Fang Fang

    题目;http://acm.hdu.edu.cn/showproblem.php?pid=5455 题意就是找出所给字符串有多少个满足题目所给条件的子串,重复的也算,坑点是如果有c,f以外的字符也是不 ...

  9. hdu 5461(2015沈阳网赛 简单暴力) Largest Point

    题目;http://acm.hdu.edu.cn/showproblem.php?pid=5461 题意就是在数组中找出a*t[i]*t[i]+b*t[j]的最大值,特别注意的是这里i和i不能相等,想 ...

随机推荐

  1. jQuery---城市选择案例

    城市选择案例 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UT ...

  2. Java8之Stream详解

    Java8中提供了Stream对集合操作作出了极大的简化,学习了Stream之后,我们以后不用使用for循环就能对集合作出很好的操作.   一.流的初始化与转换   Java中的Stream的所有操作 ...

  3. Wannafly Camp 2020 Day 2E 阔力梯的树 - set,启发式合并

    搞一波启发式合并即可 #include <bits/stdc++.h> using namespace std; #define int long long #define iter se ...

  4. VTK坐标系统及视图分割

    计算机图像学里广泛应用的坐标系统有四种,分别是:模型坐标系统(model),世界坐标系统(world),视图坐标系统(view)和显示坐标系统(display). 模型坐标系统就是定义模型时所用的坐标 ...

  5. Linux断网安装jdk1.8

    1.创建目录存放jdk包 mkdir /usr/java 2.上传jdk包 通过xftp或者其他远程工具 3.解压jdk tar zxvf jdk-8u221-linux-x64.tar.gz 4.打 ...

  6. C3P0连接技术

    1.导入jar包(两个) c3p0-0.9.5.2.jar和mchange-commons-java-0.2.12.jar导入数据库驱动jar包 2.定义配置文件 配置文件名称:c3p0.proper ...

  7. 顶级Kagglers的心得和技巧

    这是一篇笔记,课程来自Coursera上的How to Win a Data Science Competition: Learn from Top Kagglers 本篇可以算是顶级Kaggler大 ...

  8. IDEA更换背景颜色与字体

    打开IDEA 选择左上角的File  ->  Setting -> Editor  -> Color Scheme  就可以设置  黑白背景  默认为白色  可以选择  Darcul ...

  9. day01_2spring3

    Bean基于XML和基于注解的装配 一.Bean基于XML的装配 1.生命周期接着day01_1来讲(了解) Bean生命周期的如图所示:用红色框起来的都是我们要研究的! 如图Bean is Read ...

  10. 1054 The Dominant Color

    大致题意就是给出N行M列的元素,找出出现次数最多的元素并输出. #include<iostream> #include<unordered_map> using namespa ...