Loading

P1131-ZJOI时态同步

1131-ZJOI时态同步

题意:给一棵树,边有边权,求最少加上多少边权可以从根节点开始到所有叶子节点的路径一样长。

题解:树上构造。

  • 让所有叶子节点到根节点的距离是初始时最深的那个的距离是最优的。若不是最优,总可以在最深点的路径上删去加上的那一部分,并在其他叶子节点的路径上删去更多一部分,构造一个更优解。
  • 考虑到:在深度更小的路径上操作相当于在该路径子树内的分支上多次做相同操作,所以优先在深度较小的边上加边权直至不能继续加为止。这样构造方法就做出来了。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define int ll
const int maxn=5e5+10;
int n,shi,totd,ans;
struct node{
    int v;int w;
};
vector<node> yuan[maxn];
int dep[maxn],mdep[maxn];
void dfs(int now,int fa){
    totd=max(totd,dep[now]);
    mdep[now]=dep[now];
    for(int i=0;i<yuan[now].size();i++){
        int v=yuan[now][i].v,w1=yuan[now][i].w;
        if(v==fa) continue;
        dep[v]=dep[now]+w1;
        dfs(v,now);
        mdep[now]=max(mdep[now],mdep[v]);
    }
}
void dfs1(int now,int fa,int cnt){
    if(mdep[now]+cnt<totd){
        ans+=totd-(mdep[now]+cnt);
        cnt+=totd-(mdep[now]+cnt);
    }
    for(int i=0;i<yuan[now].size();i++){
        int v=yuan[now][i].v,w1=yuan[now][i].w;
        if(v==fa) continue;
        dfs1(v,now,cnt);
    }
}
signed main(){
    cin>>n>>shi;
    for(int i=1;i<n;i++){
        int a1,a2,a3;cin>>a1>>a2>>a3;
        yuan[a1].push_back((node){a2,a3});
        yuan[a2].push_back((node){a1,a3});
    }
    dfs(shi,0);
    dfs1(shi,0,0);
    cout<<ans<<endl;
    ding;return 0;
}
posted @ 2021-06-01 16:01  14long  阅读(47)  评论(0)    收藏  举报