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;
        }
    }
}
时间: 2024-10-14 10:29:22

Codeforces Round #392 (div.2) E:Broken Tree的相关文章

Codeforces Round #245 (Div. 1)——Guess the Tree

本文出自:http://blog.csdn.net/svitter 实验环境:Myeclipse10 + tomcat7.0 有时间会写windows和linux下的tomcat配置,现在时间有限,暂且不写了..有些东西也是没有理解透彻. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <%@ page language="java" contentType="

Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/problem/C Description Iahub likes trees very much. Recently he discovered an interesting tree named propagating tree. The tree consists of n nodes numb

Codeforces Round #124 (Div. 1) C. Paint Tree(极角排序)

C. Paint Tree time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given a tree with n vertexes and n points on a plane, no three points lie on one straight line. Your task is to paint

343D/Codeforces Round #200 (Div. 1) D. Water Tree dfs序+数据结构

D. Water Tree Mad scientist Mike has constructed a rooted tree, which consists of n vertices. Each vertex is a reservoir which can be either empty or filled with water. The vertices of the tree are numbered from 1 to n with the root at vertex 1. For

Codeforces Round #392 (Div. 2) F. Geometrical Progression

原题地址:http://codeforces.com/contest/758/problem/F F. Geometrical Progression time limit per test 4 seconds memory limit per test 256 megabytes input standard input output standard output For given n, l and r find the number of distinct geometrical pro

Codeforces Round #168 (Div. 1) B. Zero Tree 树形dp

题目链接: http://codeforces.com/problemset/problem/274/B 题意: 给出一棵树,每个点有权值,每次操作可以对一个联通子集中的点全部加1,或者全部减1,且每次操作必须包含点1,问最少通过多少次操作可以让整棵树每个点的权值变为0. 思路: http://blog.csdn.net/qq_24451605/article/details/48622953 定义状态up[u],down[u]代表点u被加操作的次数和点u被减操作的次数 因为必须包含点1,所以我

Codeforces Round #225 (Div. 2)---E. Propagating tree(时间戳+线段树)

Iahub likes trees very much. Recently he discovered an interesting tree named propagating tree. The tree consists of n nodes numbered from 1 to n, each node i having an initial value ai. The root of the tree is node 1. This tree has a special propert

Codeforces Round #392 (Div. 2)

A - Holiday Of Equality(water) 题意:一共给你N个数,让你向上补数值,使得最终所有数值都相等,输出最少花费. 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int INF = 0x3f3f3f3f; 5 const int maxn = 100 + 5; 6 7 int a[maxn]; 8 9 int main() 10 { 11 int n;

Codeforces Round #200 (Div. 1) D. Water Tree(dfs序加线段树)

思路: dfs序其实是很水的东西.  和树链剖分一样, 都是对树链的hash. 该题做法是:每次对子树全部赋值为1,对一个点赋值为0,查询子树最小值. 该题需要注意的是:当我们对一棵子树全都赋值为1的时候, 我们要查询一下赋值前子树最小值是不是0, 如果是的话, 要让该子树父节点变成0, 否则变0的信息会丢失. 细节参见代码: #include <cstdio> #include <cstring> #include <algorithm> #include <i