zoukankan      html  css  js  c++  java
  • AtCoder Regular Contest 098 F.Donation

    传送门

    首先,对于一个点i,进入这个点前必须大于等于Ai,每个点必须捐赠Bi
    那么我们可以在每个点最后一次经过的时候再捐赠,这样显然更优

    现在我们假设每个点都是最后一次经过的时候捐赠。现在我们把捐赠的钱排除在外,对于每个点来说,需要max(Ai-Bi, 0)才能经过这个点
    显然,max(Ai-Bi, 0)越大的点需要尽快到达,不然后面钱越来越少,就搞不定了

    如果遵循这个规律,优先走max(Ai-Bi, 0)大的点。对于每一点,步骤可以概括为走完所有的子图(剩一个不走),显然这个过程不需要耗费钱财(因为父节点max(Ai-Bi, 0)最大),最后走剩下的那个子图,也就是说讨论选哪个字图最后走比较合适

    所以我们采用树dp,从上往下构建一个递减的树
    (我觉得我还是很难说明白,如果还不懂,可以看下代码或者官方题解)

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <map>
    #include <vector>
    #include <set>
    typedef long long ll;
    using namespace std;
    const int N = 1e5+5;
    
    int n, m;
    vector<int> E[N];
    int A[N], B[N], pos[N], vis[N], fa[N];
    long long sum[N], add[N];
    inline bool cmp(int x, int y) { return A[x] < A[y]; }
    inline int find(int x) { return (x == fa[x]) ? x : (fa[x] = find(fa[x])); }
    int main() {
        while(~scanf("%d %d", &n, &m)) {
            for(int i = 1; i <= n; ++i) E[i].clear();
            for(int i = 1; i <= n; ++i) {
                pos[i] = i; vis[i] = 0; fa[i] = i;
                scanf("%d %d", &A[i], &B[i]);
                A[i] = max(0, A[i] - B[i]);
                add[i] = A[i];
                sum[i] = B[i];
            }
    
            sort(pos+1, pos+n+1, cmp);
            for(int i = 0; i < m; ++i) {
                int a, b; scanf("%d %d", &a, &b);
                E[a].push_back(b);
                E[b].push_back(a);
            }
    
            for(int i = 1; i <= n; ++i) {
                vis[pos[i]] = 1;
                for(int j = 0; j < E[pos[i]].size(); ++j) {
                    int tt = E[pos[i]][j];
                    if(vis[tt]) {
                        int f1 = find(pos[i]); int f2 = find(tt);
                        if(f1 != f2) {
                            sum[f1] += sum[f2];
                            fa[f2] = f1; 
                            add[f1] = min(add[f1], add[f2] + max(0ll, A[f1] - add[f2] - sum[f2])); 
                        }
                    }
                }
            }
            printf("%lld
    ", sum[pos[n]] + add[pos[n]]);
        }
        return 0;
    }
    
  • 相关阅读:
    基于 Web 的 Go 语言 IDE
    基于 Web 的 Go 语言 IDE
    语音芯片选型
    干簧管
    51单片机或PLC驱动3.5寸至52寸的数字TFTLCD屏、VGA接口显示器、电视机
    为什么做网线水晶头必须按照颜色顺序?
    51地图接口
    labview多个并行循环同时退出
    TCP和UDP的区别
    IMAQ Flatten Image to String VI的参数设置对比
  • 原文地址:https://www.cnblogs.com/Basasuya/p/9176539.html
Copyright © 2011-2022 走看看