P1131 [ZJOI2007] 时态同步
P1131 [ZJOI2007] 时态同步 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这更多是一个思维题
看到上面这副图,我们的想法是先让 1→2和1→3拉伸到1→4的深度,再让5→1的叶子拉伸到5→6
我们便令dis[x]为x子树中最深的深度,对x节点进行操作
我们已经在v子树的操作中让v子树的每个叶子都是深度都是等深的
令dp[x]为让x子树中每个叶子等深所需的操作次数,当然这题不是树形dp,但用到树形dp的思想
接下来便是让x子树中每个叶子等深,所以我们先要找到最深的叶子max(dis[v]+val[x][v]),令他们的距离为dis[x];
然后让v子树拉伸,拉伸的长度为:dis[x]-(dis[v]+val[x][v])。
统计dp[x]+=dp[v]+(dis[x]-(dis[v]+val[x][v]);
Code:
#include<bits/stdc++.h> using namespace std; #define ll long long #define mp make_pair #define pb push_back #define popb pop_back #define fi first #define se second const int N=5e5+10; //const int M=; //const int inf=0x3f3f3f3f; //const ll INF=0x3ffffffffffff; int T,n,root; ll dp[N],dis[N]; vector<int> g[N],val[N]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } void dfs(int x,int fa) { for(int i=0;i<g[x].size();i++) { int v=g[x][i]; if(v==fa) continue; dfs(v,x); dis[x]=max(dis[x],dis[v]+val[x][i]); } for(int i=0;i<g[x].size();i++) { int v=g[x][i]; if(v==fa) continue; dp[x]+=(dp[v]+dis[x]-dis[v]-val[x][i]); } } int main() { // freopen("","r",stdin); // freopen("","w",stdout); n=read();root=read(); for(int i=1;i<n;i++) { int u=read(),v=read(),t=read(); g[u].pb(v);val[u].pb(t); g[v].pb(u);val[v].pb(t); } dfs(root,0); printf("%lld",dp[root]); return 0; }