zoukankan      html  css  js  c++  java
  • C Decrement on the Tree(选择路径所有边权减1,问多少次操作能让所有边权等于0)

    题:https://ac.nowcoder.com/acm/contest/5675/C

    题意:选择路径所有边权减1,问最少多少次操作能让所有边权等于0,支持边修改

    分析:我们选择的路径只用考虑起点即可,对于一个节点我们用临边边权和来考量它;

       第一种情况为有一条边的边权大于总和的一半,假设差值为x,那么必然有从此节点出发的路径x条

       第二种情况为第一种情况没有发生,若总和为奇数,则必然有一条从此节点出发的路径,偶数则没有,因为一定会有由其他节点出发的路径经过它。  

       因此我们处理时只需要关注临边边权的最大值即可

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define pb push_back
    #define pii pair<int,int>
    #define MP make_pair
    const int inf=0x3f3f3f3f;
    const int M=2e5+5;
    multiset<ll>g[M];
    ll sum[M],w[M];
    int x[M],y[M];
    ll solve(int x){
        multiset<ll>::iterator it=g[x].end();
        it--;
        if(*it>sum[x]-*it)return 2*(*it)-sum[x];
        return sum[x]&1;
    }
    int main(){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++){
            scanf("%d%d%lld",&x[i],&y[i],&w[i]);
            g[x[i]].insert(w[i]);
            g[y[i]].insert(w[i]);
            sum[x[i]]+=w[i];
            sum[y[i]]+=w[i];
        }
        ll ans=0;
        for(int i=1;i<=n;i++)
            ans+=solve(i);
        printf("%lld
    ",ans/2);
        while(m--){
            int op;
            ll val;
            scanf("%d%lld",&op,&val);
            ans-=solve(x[op])+solve(y[op]);
            g[x[op]].erase(g[x[op]].find(w[op]));
            g[y[op]].erase(g[y[op]].find(w[op]));
            sum[x[op]]+=val-w[op];
            sum[y[op]]+=val-w[op];
            w[op]=val;
            g[x[op]].insert(w[op]);
            g[y[op]].insert(w[op]);
            ans+=solve(x[op])+solve(y[op]);
            printf("%lld
    ",ans/2);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    hdu1698(线段树)
    poj3468(线段树)
    hdu1394(线段树求逆序对)
    hdu1754(线段树)
    hdu1166(线段树)
    hdu2412(树形dp)
    hdu4714(树形dp)
    hdu4705(树形dp)
    hdu4679(树形dp)
    滑动导航条
  • 原文地址:https://www.cnblogs.com/starve/p/13490236.html
Copyright © 2011-2022 走看看