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不能相等,想 ...
随机推荐
- java exec python program
I find three methods, the first is using jython, the module of jython can transform the type of data ...
- upload-labs打关详解
1-19关 00x01 JS检查 方法一.修改javascript代码,将.php添加到允许上传的类型中 3.上传成功 方法二:绕过前端,通过burpsuit抓包,上传一张info.jpg图片,然后抓 ...
- ASP.NET Razor 常用示例
1.在网页中显示@符号 使用@@即可使编译器不切换到c#,这样在网页中会显示一个@符号. 2.隐式表达式 也就是正常的razor语法,不能包含空格.(除了await 如:<p>@await ...
- PyQt5-QDateEdit的简单使用
使用PyQt5开发图形界面,里面使用日期框,这里把这个QDateEdit组件命名为:beginDate from PyQt5.QtCore import QDate 1.初始化赋值,不设置则默认为20 ...
- javaScript入门(函数)
目录 JavaScript函数 函数是什么 函数返回值 return特点: 递归函数 匿名函数(anoymous) 自执行函数(通过匿名函数实现) 回调函数 闭包函数 构造函数 构造函数两大类 注意事 ...
- JS高级---正则表达式其他方法的使用
正则表达式其他方法的使用 正则表达式中:g 表示的是全局模式匹配 正则表达式中:i 表示的是忽略大小写 var str = "中国移动:10086,中国联通:10010,中国电信:10000 ...
- HTML下拉请求列表标签
select下拉请求列表 option选择项(内容) selected默认值
- Redis Desktop Manager 连接不上redis的问题
1.需要启动redis,进入后测试,ping,回应pong,说明redis可用 启动redis的代码: redis-server /myredis/redis.conf redis-cli 如果还是连 ...
- kali 所有版本
首先打开kali官方网站 第一步 第二步 找到 第三步点击标黄色的地方 http://cdimage.kali.org/ 第四步将网址中的cdimage替换为old http://old.kali.o ...
- Gol流程控制
条件语句 if语句 if 布尔表达式 { }else 布尔表达式{ }else{ } if语句后的{,一定要和if条件写在同一行,否则报错 else一定要在if语句}之后,不能自己另起一行 if语句变 ...