标签:void add str max 节点 维护 struct for 代码实现
树形DP
有一棵树,有 n 个节点, n-1 条边,每条边都有一个权值。
要求每个叶子结点到根节点的边权相同,求最少的改动数量(不是次数)
看不懂的话,走传送门
很显然是 DP (我也不知道是怎么想到的)
我们可以想一想,如果从根节点出发,向下维护会有诸多不便。
所以我们可以倒着思考,从每一个叶子结点开始进行维护,这就很方便了。
现在我们来考虑如何维护:
然后就没了。
#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 思想。
标签:void add str max 节点 维护 struct for 代码实现
原文地址:https://www.cnblogs.com/lpf-666/p/12436413.html