• 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
  • 相关阅读:
    认识AppDomain类
    认识Math类
    控制输入法
    开发中常见错误
    flash视频窗口被关闭卡住了父窗口
    TransactionScope 事务 net2.0
    发现system.collection 命名空间下面的类大部分是基于数组来存储
    utf8 编码出现空白
    如何WEB上的消息提醒
    当前不会命中断点
  • 原文地址:https://www.cnblogs.com/starve/p/13490236.html
Copyright © 2020-2023  润新知