hdoj6446(树形DP)
题目链接:https://vjudge.net/problem/HDU-6446
题意:简化题意后就是求距离和的2*(n-1)!倍。
思路:
简单的树形dp,通过求每条边的贡献计算距离和,边(u,v)的贡献为sz[v]*(n-sz[v])。
#include<cstdio>
#include<algorithm>
using namespace std; typedef long long LL;
const int maxn=1e5+;
const int MOD=1e9+;
int n,cnt,head[maxn],sz[maxn];
LL ans; struct node{
int v,nex;
LL w;
}edge[maxn<<]; void adde(int u,int v,LL w){
edge[++cnt].v=v;
edge[cnt].w=w;
edge[cnt].nex=head[u];
head[u]=cnt;
} void dfs(int u,int fa){
sz[u]=;
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].v;
if(v==fa) continue;
dfs(v,u);
sz[u]+=sz[v];
ans=(ans+edge[i].w*sz[v]%MOD*(n-sz[v])%MOD)%MOD;
}
} int main(){
while(~scanf("%d",&n)){
ans=;
cnt=;
for(int i=;i<=n;++i)
head[i]=;
for(int i=;i<n;++i){
int u,v;LL w;
scanf("%d%d%lld",&u,&v,&w);
adde(u,v,w);
adde(v,u,w);
}
dfs(,);
for(int i=;i<n;++i)
ans=ans*i%MOD;
ans=ans*%MOD;
printf("%lld\n",ans);
}
return ;
}
另外因为前几天学点分治,看到这题想到可以用点分治求距离和。具体做法是,通过求得重心u后求所有点到重心的距离dis[i],然后采用点分治的第二种写法,遍历u的所有子结点v,用sum表示前面计算过的距离总和,num表示前面的结点数,那么对当前遍历的dis[i],其贡献为num*dis[i]+sum。但要注意不要漏了以重心为端点的边,所以将num初始化1,而不是0。
点分治代码:
#include<cstdio>
#include<algorithm>
using namespace std; typedef long long LL;
const int maxn=1e5+;
const int MOD=1e9+;
const int inf=0x3f3f3f3f;
int n,cnt,head[maxn],sz[maxn],mson[maxn],Min,size,root;
int vis[maxn],t,num;
LL dis[maxn],tmp,sum,ans; struct node{
int v,nex;
LL w;
}edge[maxn<<]; void adde(int u,int v,LL w){
edge[++cnt].v=v;
edge[cnt].w=w;
edge[cnt].nex=head[u];
head[u]=cnt;
} void getroot(int u,int fa){
sz[u]=,mson[u]=;
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].v;
if(vis[v]||v==fa) continue;
getroot(v,u);
sz[u]+=sz[v];
mson[u]=max(mson[u],sz[v]);
}
mson[u]=max(mson[u],size-sz[u]);
if(mson[u]<Min) Min=mson[u],root=u;
} void getdis(int u,int fa,LL len){
dis[++t]=len;
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].v;
if(vis[v]||v==fa) continue;
getdis(v,u,(len+edge[i].w)%MOD);
}
} void solve(int u){
sum=;
num=;
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].v;
if(vis[v]) continue;
t=;
tmp=;
getdis(v,u,edge[i].w);
for(int i=;i<=t;++i){
ans=(ans+num*dis[i]%MOD+sum)%MOD;
tmp=(tmp+dis[i])%MOD;
}
sum=(sum+tmp)%MOD;
num+=t;
}
} void fenzhi(int u,int ssize){
vis[u]=;
solve(u);
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].v;
if(vis[v]) continue;
Min=inf,root=;
size=sz[v]<sz[u]?sz[v]:(ssize-sz[u]);
getroot(v,);
fenzhi(root,size);
}
} int main(){
while(~scanf("%d",&n)){
cnt=;
ans=;
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);
adde(u,v,w);
adde(v,u,w);
}
Min=inf,root=,size=n;
getroot(,);
fenzhi(root,n);
for(int i=;i<n;++i)
ans=ans*i%MOD;
ans=ans*%MOD;
printf("%lld\n",ans);
}
return ;
}
hdoj6446(树形DP)的更多相关文章
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- COGS 2532. [HZOI 2016]树之美 树形dp
可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...
- 【BZOJ-4726】Sabota? 树形DP
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 128 Solved ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 树形DP
切题ing!!!!! HDU 2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
- POJ2342 树形dp
原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
- hdu1561 The more, The Better (树形dp+背包)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...
- bzoj2500: 幸福的道路(树形dp+单调队列)
好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...
随机推荐
- linux系统编程--文件IO
系统调用 什么是系统调用: 由操作系统实现并提供给外部应用程序的编程接口.(Application Programming Interface,API).是应用程序同系统之间数据交互的桥梁. C标准函 ...
- chown 与 chgrp 修改权限用户
# 改变权限 chmod 777 filepath # 改变所有者 chown test filepath # 改变所属组 chgrp user filepath chown='change own ...
- 从斐波那契数列看java方法的调用过程
先看斐波那契数列的定义: 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为 ...
- substring(x)和substring(x,y)的用法
substring(x)和substring(x,y)的用法 代码: public class textmu { /** * @param args */ public static void mai ...
- react-redux学习初步总结
1.index.js文件中需要引入 a.React(把jsx编译到js需要调用一个函数, 这个函数在React叫React.createElement. 解答地址:https://segmentfau ...
- 解决vue中使用laydate.js选择日期后再修改其他model时日期会被清空问题
首先描述一下问题,下图中均绑定v-model,例如先选择出生开始时间,然后当再选择地区或其他选项时该时间就会被清空 首先看一下我这边开始的默认值,开始我设置都为空 当我选择如下图的生日开始时间与结束时 ...
- 图解Python 【第五篇】:面向对象-类-初级基础篇
由于类的内容比较多,分为类-初级基础篇和类-进阶篇 类的内容总览图: 本节主要讲基础和面向对象的特性 本节内容一览图: 前言总结介绍: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 ...
- SpringCloud(六)之 网关概念、Zuul项目搭建-(利用Zuul 实现鉴权和限流实战)
一.网关概念 1.什么是路由网关 网关是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能 提供路由请求.鉴权.监控.缓存.限流等功能.它将"1对N"问题转换成 ...
- C++ STL——deque
目录 一 deque容器 1.1 deque容器基本概念 1.2 deque构造函数 1.3 deque赋值操作 1.4 deque大小操作 1.5 deque双端插入和删除操作 1.6 deque数 ...
- Nginx优化之服务性能优化
优化Nginx服务的worker进程个数 修改nginx主配置文件 worker_processes 1; #指定了Nginx要开启的进程数,结尾数字就是进程个数 Nginx有Master进程和wor ...