码迷,mamicode.com
首页 > 其他好文 > 详细

P1131 [ZJOI2007]时态同步

时间:2020-03-07 21:15:28      阅读:79      评论:0      收藏:0      [点我收藏+]

标签:void   add   str   max   节点   维护   struct   for   代码实现   

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\n",ans);
   //system("pause");
   return 0;
}

结语

其实这道题接近模拟,但也有 DP 思想。

P1131 [ZJOI2007]时态同步

标签:void   add   str   max   节点   维护   struct   for   代码实现   

原文地址:https://www.cnblogs.com/lpf-666/p/12436413.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!