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

题意:求任意俩点之间距离之和模3后的三个结果的总数(原距离之和)

第一种做法:

树形dp

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
const int M=1e4+;
const int mod=1e9+;
struct node{
int v;
ll w;
};
ll C[M][],S[M][],ans[M];
//C[i][j]:表示以i为根,然后路径消耗取模后为j的路径数
//S[i][j]:表示以i为根,路径消耗取模后为j的路径总消耗
vector<node>e[M];;
void dfs(int u,int f,ll pre){
C[u][]=C[u][]=C[u][]=;
S[u][]=S[u][]=S[u][]=;
int len=e[u].size();
for(int i=;i<e[u].size();i++){
int v=e[u][i].v;
if(v==f)
continue;
dfs(v,u,e[u][i].w);
//算跨越跟节点的贡献
for(int p=;p<;p++){
for(int j=;j<;j++)
for(int k=;k<;k++)
if(p==(j+k)%)
ans[p]=(ans[p]+S[u][j]*C[v][k]%mod+C[u][j]*S[v][k]%mod)%mod;
}
for(int j=;j<;j++){
C[u][j]=(C[u][j]+C[v][j])%mod;
S[u][j]=(S[u][j]+S[v][j])%mod;
} } for(int i=;i<;i++)//算以u为跟对答案的贡献,就直接算u的每一个子树的贡献 ans[i]=(ans[i]+S[u][i])%mod;
ll c[],s[];
memset(c,0ll,sizeof(c));
memset(s,0ll,sizeof(s));
for(int i=;i<;i++){
int t=(i-pre%+)%;
c[i]=(c[i]+C[u][t])%mod;
s[i]=(s[i]+(S[u][t]+C[u][t]*pre%mod)%mod)%mod;
}
if(f!=)
c[pre%]=(c[pre%]+1ll)%mod,s[pre%]=(s[pre%]+pre)%mod;
for(int i=;i<;i++)
C[u][i]=c[i],S[u][i]=s[i];
}
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=;i<=n;i++)
e[i].clear();
memset(S,,sizeof(S));
memset(C,,sizeof(C));
for(int i=;i<n;i++){
int u,v;
ll w;
for(int i=;i<;i++)
ans[i]=0ll;
scanf("%d%d%lld",&u,&v,&w);
u++,v++;
e[u].pb(node{v,w});
e[v].pb(node{u,w});
}
dfs(,,);
printf("%lld %lld %lld\n",ans[]*2ll%mod,ans[]*2ll%mod,ans[]*2ll%mod); }
return ;;
}

第二种做法:

点分治

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=2e4+;
const ll mod=1e9+;
struct node{
int v,nextt;
ll w;
}e[M<<];
ll sum[],disnum[],dissum[];
int head[M],vis[M],sz[M],maxv[M],tot,n,maxx,root;
void addedge(int u,int v,ll w){
e[tot].v=v;
e[tot].nextt=head[u];
e[tot].w=w;
head[u]=tot++;
}
void dfssz(int u,int f){
maxv[u]=;
sz[u]=;
for(int i=head[u];~i;i=e[i].nextt){
int v=e[i].v;
if(v==f||vis[v])
continue;
dfssz(v,u);
sz[u]+=sz[v];
maxv[u]=max(maxv[u],sz[v]);
}
}
void dfsroot(int r,int u,int f){
maxv[u]=max(maxv[u],sz[r]-sz[u]);
if(maxx>maxv[u]){
maxx=maxv[u];
root=u;
}
for(int i=head[u];~i;i=e[i].nextt){
int v=e[i].v;
if(v==f||vis[v])
continue;
dfsroot(r,v,u);
}
}
void dfsdis(int u,int f,ll d){
// if(f!=-1&&d!=0)
disnum[d%]++;
disnum[d%]%=mod;
dissum[d%]+=d;
dissum[d%]%=mod;
for(int i=head[u];~i;i=e[i].nextt){
int v=e[i].v;
if(vis[v]||v==f)
continue;
dfsdis(v,u,(d+e[i].w)%mod);
}
}
void cal(int u,ll d,int flag){
for(int i=;i<;i++)
dissum[i]=disnum[i]=; dfsdis(u,-,d);
for(int i=;i<;i++)
for(int j=;j<;j++){
int t=(i+j)%;
sum[t]=(sum[t]+flag*((disnum[i]*dissum[j]%mod+disnum[j]*dissum[i]%mod)%mod)%mod+mod)%mod;
}
}
void solve(int u){
maxx=n;
dfssz(u,-);
dfsroot(u,u,-);
cal(root,0ll,);//+
vis[root]=;
for(int i=head[root];~i;i=e[i].nextt){
int v=e[i].v;
if(vis[v])
continue;
cal(v,e[i].w,-);
solve(v);
}
}
int main(){
while(~scanf("%d",&n)){
sum[]=sum[]=sum[]=;
tot=;
for(int i=;i<=n;i++)
head[i]=-,vis[i]=;;
for(int i=;i<n;i++){
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
u++,v++;
addedge(u,v,w);
addedge(v,u,w);
}
solve();
printf("%lld %lld %lld\n",sum[],sum[],sum[]);
}
return ;
}

D. Fish eating fruit的更多相关文章

  1. Fish eating fruit 沈阳网络赛(树形dp)

    Fish eating fruit \[ Time Limit: 1000 ms \quad Memory Limit: 262144 kB \] 题意 大体的题意就是给出一棵树,求每一对点之间的距离 ...

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

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

  3. 2019 沈阳网络赛 Fish eating fruit

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

  4. The Preliminary Contest for ICPC Asia Shenyang 2019 D. Fish eating fruit(树形dp)

    题意:求一棵树上所有路径和模3分别为0 1 2 的权值的和 思路:树形dp 增加一个记录儿子节点满足条件的个数的数组 不要放在一起dp不然答案跟新会有问题 #include <bits/stdc ...

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

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

  6. 2019ICPC沈阳网络赛-D-Fish eating fruit(树上DP, 换根, 点分治)

    链接: https://nanti.jisuanke.com/t/41403 题意: State Z is a underwater kingdom of the Atlantic Ocean. Th ...

  7. The Preliminary Contest for ICPC Asia Shenyang 2019

    传送门 B. Dudu's maze 题意: 是什么鬼东西???我读题可以读半小时QAQ 给出一张无向图,一个人在里面收集糖果,每个点都有一个糖果,特殊点除外.当他第一次进入特殊点时,会随机往一条边走 ...

  8. SpringRMI远程方法调用

    Spring为各种远程访问技术的集成提供了工具类. 该小段引用自 http://www.open-open.com/lib/view/open1408957290478.html Spring远程支持 ...

  9. SpringRMI远程方法调用【原】

    Spring为各种远程访问技术的集成提供了工具类. 该小段引用自 http://www.open-open.com/lib/view/open1408957290478.html Spring远程支持 ...

随机推荐

  1. unzip 小坑

    unzip test.zip 直接将zip解压到当前目录下,保留test级目录. unzip test.war 直接将.war解压到当前目录,不保留test级目录,所以建议使用 unzip test. ...

  2. CSS 宽,高,背景设置

    width 宽,height 高,background 背景:背景色 background-color:颜色值--英文单词/十六进制/rgb:背景图 background-image:url(‘图片路 ...

  3. JFrame的面板结构和JPanel的使用

    JFrame图解结构 有一窗口框架实例:JFrame win = new JFrame("窗口");在new JFrame()时,构建了JFrame实例对象,在实例中的Layere ...

  4. .NET微信开发 配置微信公众号基本配置的几种方法

    自己最近搞了公众号,记录一下. 目的就是为了在微信公众号里启用服务器配置. 微信文档 其实微信文档已经写得很清楚了,也很简单.(微信的目的就是它发送一个get请求,希望我们能接受一下,然后给微信回个数 ...

  5. .net core excel导入导出

    做的上一个项目用的是vs2013,传统的 Mvc模式开发的,excel报表的导入导出都是那几段代码,已经习惯了. 导入:string filename = ExcelFileUpload.FileNa ...

  6. C++ spdlog日志管理

    [1]spdlog简介 spdlog是一个开源的.快速的.仅有头文件的基于C++11实现的一款C++专用日志管理库. [2]源码下载 下载地址:https://github.com/gabime/sp ...

  7. 元祖&字典

    #什么是元祖:元祖是一个不可变的列表(没有改的需求) #======================================基本使用============================== ...

  8. 增删改查(简单版&连接数据库)

    这个博客也是补充之前的学习内容: 项目总述:这个增删改查我以,选课名称,选课教室,选课教师基本信息,作为主要的信息来源.主要对这些信息最基本的增删改查 详细的分析与说明: 1.首先在src文件里定义四 ...

  9. C语言-再论指针与数组

    指针与数组的天生姻缘1.以指针方式来访问数组元素(1).数组元素使用时不能整体访问,只能是单个访问.访问形式有两种:数组形式和指针形式.(2).数组形式访问数组元素:数组名[下标]:(下标从0开始(3 ...

  10. 数据处理pandas

    1.缺失值时间戳不为NaN,为NaT, 同样判断都为isna()或notna()方法2.删值\去重 df.dropna() df.drop_duplicates() 3.上下值插值 df.fillna ...