zoukankan      html  css  js  c++  java
  • [ZJOI2007] 时态同步

    题面

        显然的一个建模是,每个叶子对应一个权值,代表比最晚的叶子早了多久,然后我们要做的就是给每条边赋上值,使得每个叶子到根的路径上的所有边权值和等于叶子的权值。

        我们贪心的想一想,必然是离根越近的边赋值多的情况比较优(在保证同步的情况下),因为离根越近的边影响的叶子会更多。

        而对于两个节点 u,v,我们必须要在lca(u,v)以下的边中赋值使得 u和v同步,因为再往上的边对u和v的影响就相同了。

        于是根据以上两点,可以得到一个比较简单的dp。

         f[x]表示以x为根的子树所有叶子同步的最小代价,转移很简单,留给大家想了w

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=500005;
    
    int hd[N],ne[N*2],to[N*2],val[N*2],num,n,S,mx[N];
    ll f[N];
    
    inline void add(int x,int y,int z){
    	to[++num]=y,ne[num]=hd[x],hd[x]=num,val[num]=z;
    } 
    
    inline int read(){
        int x=0; char ch=getchar();
        for(;!isdigit(ch);ch=getchar());
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x;
    }
    
    void dfs(int x,int fa){
    	for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa)
    		dfs(to[i],x),mx[x]=max(mx[x],mx[to[i]]+val[i]);
    	
    	for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa)
    	    f[x]+=f[to[i]]+mx[x]-mx[to[i]]-val[i];
    }
    
    int main(){
    	n=read(),S=read();
    	for(int i=1,u,v,w;i<n;i++) u=read(),v=read(),w=read(),add(u,v,w),add(v,u,w);
    	
    	dfs(S,0);
    	
    	printf("%lld
    ",f[S]);
    	return 0;
    }
    

      

  • 相关阅读:
    [Luogu1126] 机器人搬重物
    [POJ1830] 开关问题
    [bzoj3139] 比赛
    [POJ3349] Snowflake Snow Snowflakes
    The Tour
    [POJ3740] Easy Finding
    [vijos1453] 曼哈顿距离
    [POJ1632] Vase collection
    Codewars笔记
    Appium知识积累
  • 原文地址:https://www.cnblogs.com/JYYHH/p/11258074.html
Copyright © 2011-2022 走看看