洛谷 P1131 [ZJOI2007]时态同步(dfs)
链接
观察题目
我们发现所给图为一棵树,则终止节点就为叶子节点,我们dfs一遍即可
先看代码吧
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=5e5+4;
int maxx=-1;
inline int read(){
int ret=0;
int f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-f;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
ret=ret*10+(ch^'0');
ch=getchar();
}
return f*ret;
}
int n;
int s;
long long ans;
int head[maxn];
struct edge{
int nex;
int to;
int w;
}e[maxn];
int cnt;
int m[maxn];
void add(int u,int to,int w){
cnt++;
e[cnt].to=to;
e[cnt].w=w;
e[cnt].nex=head[u];
head[u]=cnt;
}
void dfs(int u,int fa){
for(int i=head[u];i;i=e[i].nex){
if(e[i].to!=fa)
dfs(e[i].to,u);
}
for(int i=head[u];i;i=e[i].nex){
if(e[i].to!=fa){
m[u]=max(m[u],e[i].w);
}
}
for(int i=head[u];i;i=e[i].nex){
if(e[i].to!=fa){
ans+=m[u]-e[i].w;
}
}
for(int i=head[fa];i;i=e[i].nex){
if(e[i].to==u)
e[i].w+=m[u];
}
return;
}
int main(){
// freopen("a.in","r",stdin);
n=read();
s=read();
int x,y,z;
for(int i=1;i<n;i++){
x=read();
y=read();
z=read();
add(x,y,z);
add(y,x,z);
// cout<<x<<" "<<y<<" "<<z<<endl;
}
for(int i=1;i<=n;i++){
m[i]=-1;
}
dfs(s,0);
for(int i=1;i<=n;i++){
// cout<<i<<" "<<m[i]<<endl;
}
cout<<ans;
return 0;
}
看着好像挺长但其实挺好理解
解释一下吧
本质上更新过的父节点变成了从父节点到子树中叶子节点的最大权值和
即从父节点到叶子节点所需费用的最大值
我们先dfs到最低层
然后从后向前更新
还是很好理解的,画个简单图推一下即可