2019沈阳网赛树形dp
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的更多相关文章
- HDU 6201 2017沈阳网络赛 树形DP或者SPFA最长路
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6201 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过 ...
- 2019 沈阳网络赛 D Fish eating fruit ( 树形DP)
题目传送门 题意:求一颗树中所有点对(a,b)的路径长度,路径长度按照模3之后的值进行分类,最后分别求每一类的和 分析:树形DP \(dp[i][j]\) 表示以 i 为根的子树中,所有子节点到 i ...
- 2019 沈阳网络赛 Fish eating fruit
这题看了三个月,终于过了,第一次看的时候没学树形DP,想用点分治但是不会 后来学了二次扫描,就有点想法了.... 这东西也真就玄学了吧... #include<iostream> #inc ...
- 2015年沈阳网赛 Jesus Is Here(DP中的计数问题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5459 题目描述:给定一个递推得来的字符串,问字符串中不同cff之间的距离之和, 递推规则: s1=c; ...
- hdu 4274 2012长春赛区网络赛 树形dp ***
设定每个节点的上限和下限,之后向上更新,判断是否出现矛盾 #include<cstdio> #include<iostream> #include<algorithm&g ...
- [2019沈阳网络赛D题]Dawn-K's water(点分治)
题目链接 题意为求出树上任意点对的距离对3取余的和. 比赛上听到题意就知道是点分治了,但是越写越不对劲,交之前就觉得会T,果不其然T了.修修改改结果队友写了发dp直接就过了Orz. 赛后想了想维护的东 ...
- hdu5461 Largest Point(沈阳网赛)
Largest Point Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total ...
- hdu 5455 (2015沈阳网赛 简单题) Fang Fang
题目;http://acm.hdu.edu.cn/showproblem.php?pid=5455 题意就是找出所给字符串有多少个满足题目所给条件的子串,重复的也算,坑点是如果有c,f以外的字符也是不 ...
- hdu 5461(2015沈阳网赛 简单暴力) Largest Point
题目;http://acm.hdu.edu.cn/showproblem.php?pid=5461 题意就是在数组中找出a*t[i]*t[i]+b*t[j]的最大值,特别注意的是这里i和i不能相等,想 ...
随机推荐
- CSS隐藏元素的五种方法
1.opacity:0 2.visibility:hidden 3.diaplay:none 4.position:absolute display display属性依照词义真正隐藏元素.将disp ...
- Pi和e的积分
Evaluate integral $$\int_{0}^{1}{x^{-x}(1-x)^{x-1}\sin{\pi x}dx}$$ Well,I think we have $$\int_{0}^{ ...
- navicat永久激活
https://jingyan.baidu.com/article/f54ae2fc51f0311e92b84998.html
- MySQL安装版安装过程
步骤1 步骤2 步骤3 步骤4 步骤5 步骤6 步骤7 步骤8 步骤9 步骤10 步骤11 步骤12
- execute、executeUpdate、executeQuery的区别
链接:https://blog.csdn.net/u012501054/article/details/80323176 链接:https://blog.csdn.net/CNAHYZ/article ...
- nginx启动时指定配置文件
下载源文件方式安装nginx 会在/usr/local目录下安装nginx 此时虚拟机系统中会有两个nginx 如果启动的时候没有指定配置文件的位置,默认读取的配置文件就是/usr/local/ngi ...
- Python基础教程-02
<Python基础教程> 第3章 使用字符串 字符串方法find返回的并非布尔值.如果find像这样返回0,就意味着它在索引0处找到 了指定的子串 join可合并一个字符串列表,不能合并数 ...
- HashMap源码(一)
本文主要是从学习的角度看HashMap源码 HashMap的数据结构 HashMap是一个数组+链表的结构(链表散列),每个节点在HashMap中以一个Node存在: HashMap的初始化 publ ...
- 关于setTimeout的妙用
定义 在指定的延迟时间之后调用一个函数或执行一个代码片段 这个是setTimeout最主要的功能,但也是很坑的地方,首先javascript其实是运行在单线程的环境下,意味者定时器会在未来的某个时间支 ...
- AcWing 1016. 最大上升子序列和
#include<iostream> using namespace std ; ; int f[N]; int a[N]; int main() { int n; cin>> ...