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]时态同步的主要内容,如果未能解决你的问题,请参考以下文章

P1131 [ZJOI2007]时态同步

P1131 [ZJOI2007] 时态同步

P1131 [ZJOI2007] 时态同步

P1131 [ZJOI2007]时态同步

P1131 [ZJOI2007]时态同步

洛谷P1131[ZJOI2007]时态同步