zoukankan      html  css  js  c++  java
  • Codeforces Round #392 (div.2) E:Broken Tree

    orz一开始想不画图做这个题(然后脑袋就炸了,思维能力有待提高)

    我的做法是动态规划+贪心+构造

    首先把题目给的树变成一个可行的情况,同时weight最小

    这个可以通过动态规划解决 dp[x]表示以x为结点的子树,它的最小weight是多少

    接着我们就只需要考虑每条边增加多少就可以了,这里可以用贪心的做法

    ddfs(int x, int fa, int v) 这里v是表示给x结点最大多少增量,然后慢慢加就可以,返回没用掉的增量

    其实这个做法有点奇怪,应该有更简便的做法(我觉得可以直接贪心做)

    #include <iostream>
    #include <cstdio>
    #include <vector>
    using namespace std;
    const int maxn = 4*111111;
    const long long Give = 2e18;
    struct Edge
    {
        int from, to;
        long long w, v;
    };
    vector<Edge> edges;
    vector<int> G[maxn];
    long long dp[maxn], delta[maxn], dd[maxn], Fail;
    void addedge(int from, int to, int w, int v)
    {
        edges.push_back((Edge){from, to, w, v});
        edges.push_back((Edge){to, from, w, v});
        int m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    
    void dfs(int x, int fa)
    {
        dp[x] = 0;
        for(int i = 0; i < G[x].size(); i++)
        {
            Edge &e = edges[G[x][i]];
            if(e.to == fa) continue;
            dfs(e.to, x);
            if(e.v - dp[e.to] < 0) Fail = 1;
            delta[G[x][i]] = min(e.w-1, e.v - dp[e.to]);
            dp[x] += (e.w - delta[G[x][i]] + dp[e.to]);
        }
    }
    
    long long ddfs(int x, int fa, long long v)
    {
        long long ans = 0;
        //cout<<x<<endl<<endl;
        for(int i = 0; i < G[x].size(); i++)
        {
            Edge &e = edges[G[x][i]];
            if(e.to == fa) continue;
            long long t = min(v, delta[G[x][i]]);
            ans += t; v -= t;
            dd[G[x][i]] = delta[G[x][i]] - t;
            dd[G[x][i]^1] = dd[G[x][i]];
            long long dt = ddfs(e.to, x, min(v, e.v-dd[G[x][i]]-dp[e.to]));
            ans += dt; v -= dt;
        }
        return ans;
    }
    
    int n, x, y, w, v;
    int main()
    {
        //freopen("a.txt", "r", stdin);
        cin.sync_with_stdio(false);
        cin>>n;
        for(int i = 1; i < n; i++)
        {
            cin>>x>>y>>w>>v;
            addedge(x, y, w, v);
        }
        dfs(1, 1);
        //for(int i = 1; i <= n; i++) cout<<i<<" "<<dp[i]<<endl;
        if(Fail) cout<<"-1";
        else
        {
            ddfs(1, 1, Give);
            cout<<n<<endl;
            for(int i = 0; i < 2*(n-1); i += 2)
            {
                Edge &e = edges[i];
                cout<<e.from<<" "<<e.to<<" "<<e.w - dd[i]<<" "<<e.v - dd[i]<<endl;
            }
        }
    }
  • 相关阅读:
    Optimal Milking
    Alice's Chance
    The Perfect Stall
    项目范围管理
    计算机网络总结 第六章 网络层
    计算机网络总结 第一章 计算机网络概论
    Http与url
    javaScript期末复习基础
    计算机网络各层涉及协议
    javaScript_canvas 面向对象实现
  • 原文地址:https://www.cnblogs.com/Saurus/p/6358927.html
Copyright © 2011-2022 走看看