BZOJ_1060_时态同步_树形DP

题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1060

分析:水水的树形DP。

用儿子的最大值更新父亲,边更新边累加ans。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1000010
#define LL long long
int head[N],to[N<<1],nxt[N<<1],val[N<<1],cnt,n,root;
LL ans,f[N];
inline void add(int u,int v,int w){
    to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;val[cnt]=w;
}
void read(int &x){
    int f=1;x=0;char s=getchar();
    while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘&&s<=‘9‘){x=(x<<3)+(x<<1)+s-‘0‘;s=getchar();}
    x*=f;
}
void dfs(int x,int y){
    LL sum=0;
    for(int i=head[x];i;i=nxt[i]){
        if(to[i]!=y){
            dfs(to[i],x);
            sum=max(sum,f[to[i]]+val[i]);
        }
    }
    f[x]=sum;
    for(int i=head[x];i;i=nxt[i]){
        if(to[i]!=y){
        ans+=sum-(f[to[i]]+val[i]);
        }
    }
}
int main(){
    read(n);read(root);
    int x,y,z;
    for(int i=1;i<n;i++){
        read(x),read(y),read(z);
        add(x,y,z);add(y,x,z);
    }
    dfs(root,0);
    printf("%lld",ans);
}

原文地址:https://www.cnblogs.com/suika/p/8457502.html

时间: 2024-08-29 22:22:29

BZOJ_1060_时态同步_树形DP的相关文章

【BZOJ 1060】 1060: [ZJOI2007]时态同步 (树形DP)

1060: [ZJOI2007]时态同步 Description 小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数 字1,2,3-.进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路板的任何两个节点,都存在且仅 存在一条通路(通路指连接两个元件的导线序列).在电路板上存在一个特殊的元件称为"激发器".当激发器工 作后,产生一个激励电流,通过导线传向每一个它所连接的节点.而中间节点接收到激励电流后,得到信息,并将 该激励电流传向

【Luogu】P1131时态同步(树形DP)

题目链接 甚矣吾衰也!这么简单的DP我都不会了 太恐怖了 树形DP,从子树里选出时间最长的来,剩下的调到这个最长时间即可. #include<cstdio> #include<cctype> #include<algorithm> #include<cstring> using std::max; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(c

P1131 [ZJOI2007]时态同步(树形dp)

P1131 [ZJOI2007]时态同步 设$f[i]$为与$i$与最远的点的距离 在dfs时每次更新的时候顺便统计一下长度,不同的话就改成最长的那条并更新答案 #include<iostream> #include<cstdio> #include<cstring> #include<cctype> #define re register using namespace std; void read(int &x){ char c=getchar(

bzoj 1060: [ZJOI2007]时态同步【树形dp】

可能算不上dp,大概是个树形模拟 先一遍dfs算出f[u]为每个点最深的叶子到u的距离,然后再dfs一下,ans加上f[u]-f[e[i].to]-e[i].va,f[u]-f[e[i].to]是这条边应该的用时 #include<iostream> #include<cstdio> using namespace std; const int N=500005; int n,m,cnt,f[N],h[N]; long long ans; struct qwe { int ne,t

LuoguP1131 [ZJOI2007]时态同步 (树形DP,贪心)

贪心就离根最大距离 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define R(a,b,c) for(register int a = (b); a <= (c); ++ a) #define nR(a,b,c) for(register int a = (b); a >= (c); -

算法提高 金属采集_树形dp

算法提高 金属采集 时间限制:1.0s   内存限制:256.0MB 问题描述 人类在火星上发现了一种新的金属!这些金属分布在一些奇怪的地方,不妨叫它节点好了.一些节点之间有道路相连,所有的节点和道路形成了一棵树.一共有 n 个节点,这些节点被编号为 1~n .人类将 k 个机器人送上了火星,目的是采集这些金属.这些机器人都被送到了一个指定的着落点, S 号节点.每个机器人在着落之后,必须沿着道路行走.当机器人到达一个节点时,它会采集这个节点蕴藏的所有金属矿.当机器人完成自己的任务之后,可以从任

BZOJ_4726_[POI2017]Sabota?_树形DP

Description 某个公司有n个人, 上下级关系构成了一个有根树.其中有个人是叛徒(这个人不知道是谁).对于一个人, 如果他 下属(直接或者间接, 不包括他自己)中叛徒占的比例超过x,那么这个人也会变成叛徒,并且他的所有下属都会变 成叛徒.你要求出一个最小的x,使得最坏情况下,叛徒的个数不会超过k. Input 第一行包含两个正整数n,k(1<=k<=n<=500000). 接下来n-1行,第i行包含一个正整数p[i+1],表示i+1的父亲是p[i+1](1<=p[i+1]&

[bzoj1812][IOI2006]riv_多叉树转二叉树_树形dp

riv bzoj-1812 IOI-2006 题目大意:给定一棵n个点树,要求在上面建立k个收集站.点有点权,边有边权,整棵树的代价是每个点的点权乘以它和它的最近的祖先收集站的距离积的和. 注释:$1\le n \le 100$,$1\le k \le 50$. 想法:显然,这是一道树形dp题.状态也非常容易... ...只不过,我们好像要枚举子集... 所以,我们这里有一个黑科技:多叉树转二叉树. 我们先把它转成二叉树,然后再进行转移即可. 状态:dp[i][j][k]表示以i为根的子树中选出

[bzoj2657][Zjoi2012]旅游 journey_ 对偶图_树形dp

旅游 bzoj-2657 Zjoi-2012 题目大意:题目链接 注释:$1\le K\le 2\cdot 10^5$. 想法:这题... 感觉和上一个题的提示有些类似,就是题目生怕你不知道这是一道对偶图的题... ... 我们先把它转成对偶图.然后我们只把分割n变形的线段两侧的点之间连边,这样就是一棵树. 紧接着我们想要遍历最多的城市,其实就是找树上直径.树形dp即可. 最后,附上丑陋的代码... ... #include <iostream> #include <cstdio>