P1131 [ZJOI2007]时态同步

题解:

显然 我们在越高的地方增加越好,然后注意这个最大值不能经过这里,

一次dfs找最大值,

一次dfs处理每个点的min

然后最后一次dfs计算答案

依次往下找就行了

#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,a,n) for(int i=n;i>=a;--i)
#define pb push_back
#define fi first
#define se second
#define io std::ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, INF = 0x3f3f3f3f;
inline int lson(int x){return x*2;}
inline int rson(int x){return x*2+1;}
ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
ll qpow(ll a,ll n)
{
    ll r=1%P;
    for (a%=P; n; a=a*a%P,n>>=1)if(n&1)r=r*a%P;
    return r;
}
struct node
{
    int to;
    int w;
    node(){}
    node(int x,int y)
    {
        to=x;
        w=y;
    }
};
const int maxn=5e5+10;
vector<node> edg[maxn];
ll _min[maxn];
ll _max;
ll ans;
void dfs(int u,int fa,ll dis)
{
    int flag=1;
    for(auto x:edg[u])
    {
        int v=x.to;
        if(v==fa)continue;
        flag=0;
        int w=x.w;
        dfs(v,u,dis+1ll*w);
    }
    if(flag)
    {
        _max=max(_max,dis);
        _min[u]=dis;
    }
}
void dfs2(int u,int fa)
{
    int flag=1;
    for(auto x:edg[u])
    {
        int v=x.to;
        if(v==fa)continue;
        dfs2(v,u);
        flag=0;
        _min[u]=min(_min[u],_min[v]);
    }
    if(flag)
    {   if(_min[u]<_max)
        _min[u]=_max-_min[u];
        else
        _min[u]=-1;
    }
}
void dfs3(int u,int fa,ll cnt)
{
    if(_min[u]!=-1)
    {
     ans+=_min[u]-cnt;
     cnt=_min[u];
    }
    for(auto x:edg[u])
    {
        int v=x.to;
        if(v==fa)continue;
        dfs3(v,u,cnt);
    }
}
int main()
{
    io;
    int n;
    cin>>n;
    int rt;
    cin>>rt;
    memset(_min,INF,sizeof(_min));
    for(int i=1;i<n;i++)
    {
        int x,y,t;
        cin>>x>>y>>t;
        edg[x].push_back(node(y,t));
        edg[y].push_back(node(x,t));
    }
    dfs(rt,0,0);
    dfs2(rt,0);
    dfs3(rt,0,0);
    cout<<ans<<endl;

}
原文地址:https://www.cnblogs.com/acmLLF/p/13672347.html