P1131 [ZJOI2007]时态同步
Posted lpf-666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1131 [ZJOI2007]时态同步相关的知识,希望对你有一定的参考价值。
P1131 [ZJOI2007]时态同步
树形DP
题意描述
有一棵树,有 n 个节点, n-1 条边,每条边都有一个权值。
要求每个叶子结点到根节点的边权相同,求最少的改动数量(不是次数)
看不懂的话,走传送门
算法分析
很显然是 DP (我也不知道是怎么想到的)
我们可以想一想,如果从根节点出发,向下维护会有诸多不便。
所以我们可以倒着思考,从每一个叶子结点开始进行维护,这就很方便了。
现在我们来考虑如何维护:
- 从根节点出发,搜索到叶子结点,回溯时进行维护。
- 维护时,先处理出所有子节点到该点最大边权。
- ans+=最大边权与其它边权的差值。
- 将这个节点到其父亲节点的边+最大边权。
- 输出 ans 即为答案。
然后就没了。
代码实现
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
#include<cmath>
#define maxn 500500
using namespace std;
int n,s,maxd[maxn],cnt=0,head[maxn];
long long ans=0;
struct node{
int next,to,val;
}edge[maxn];
void addedge(int x,int y,int v){
edge[++cnt].next=head[x];
edge[cnt].to=y;
edge[cnt].val=v;
head[x]=cnt;
}
void dfs(int x,int fa){
for(int i=head[x];i;i=edge[i].next){
if(edge[i].to==fa) continue;
dfs(edge[i].to,x);
maxd[x]=max(maxd[x],edge[i].val);
}
for(int i=head[x];i;i=edge[i].next){
if(edge[i].to==fa) continue;
ans+=maxd[x]-edge[i].val;
}
for(int i=head[fa];i;i=edge[i].next){
if(edge[i].to==x) edge[i].val+=maxd[x];
}
return;
}
int main(){
scanf("%d %d",&n,&s);
int a,b,c;
for(int i=1;i<n;i++){
scanf("%d %d %d",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);
}
dfs(s,0);
printf("%lld
",ans);
//system("pause");
return 0;
}
结语
其实这道题接近模拟,但也有 DP 思想。
以上是关于P1131 [ZJOI2007]时态同步的主要内容,如果未能解决你的问题,请参考以下文章