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

    洛咕

    题意:给定一棵(N(N<=500000))个节点的树以及树根编号,每次操作可以使得一条边的边权加1,求使得根节点到所有叶子节点距离相同需要的最少操作次数.

    分析:显然当一棵子树内的所有叶子节点到根节点的路径都需要增加边权时,给越上面的边增加边权越好.但是我们发现如果从树根往下处理,判断,加边权后的路径距离更新等等并不太好实现.

    考虑从叶子节点往上推,这也是树形DP的一般过程.为什么从叶子节点往上推会比较好处理呢,试想一棵3个节点的子树,就是一个父亲节点,下面两个儿子节点,我们只要求出两个叶子节点分别到父亲节点的距离,记为(f[i]),那么距离小的那个一定需要增加边权.也就是说从下往上推,每一步判断是否增加边权,增加多少边权,都是可以确定的.

    不开long long会WA最后两个点.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=500005;
    ll ans,f[N];
    int tot,head[N],nxt[N*2],to[N*2],w[N*2];
    inline void add(int a,int b,int c){
    	nxt[++tot]=head[a];head[a]=tot;
    	to[tot]=b;w[tot]=c;
    }
    inline void dfs(int u,int fa){
    	for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];
    		if(v==fa)continue;
    		dfs(v,u);
    		f[u]=max(f[u],f[v]+w[i]);//找到最大距离
    	}
    	for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];
    		if(v==fa)continue;
    		ans+=f[u]-(f[v]+w[i]);//增加边权
    	}
    }
    int main(){
    	int n=read(),root=read();
    	for(int i=1;i<n;++i){
    		int a=read(),b=read(),c=read();
    		add(a,b,c);add(b,a,c);
    	}
    	dfs(root,0);
    	printf("%lld
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    使用清华源进行pip install
    BERT和ULMFIT embedding比较文本分类结果
    Ubuntu16.04更新python3.5到python3.7
    base64方式显示控件
    在使用redis做缓存后,mybatis的延迟加载失效
    springboot:redis反序列化发生类型转换错误
    eclipse :代码自动补全不生效解决办法
    微信扫码支付:问题集锦
    微信扫码支付(4):统一下单
    微信扫码支付(3):获取验签秘钥
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11311988.html
Copyright © 2011-2022 走看看