zoukankan      html  css  js  c++  java
  • Atcoder Grand Contest 010 C

    C - Cleaning

    题目连接:

    http://agc010.contest.atcoder.jp/tasks/agc010_c

    Description

    There is a tree with N vertices, numbered 1 through N. The i-th of the N−1 edges connects vertices ai and bi.

    Currently, there are Ai stones placed on vertex i. Determine whether it is possible to remove all the stones from the vertices by repeatedly performing the following operation:

    Select a pair of different leaves. Then, remove exactly one stone from every vertex on the path between those two vertices. Here, a leaf is a vertex of the tree whose degree is 1, and the selected leaves themselves are also considered as vertices on the path connecting them.
    Note that the operation cannot be performed if there is a vertex with no stone on the path.

    Input

    The input is given from Standard Input in the following format:

    N
    A1 A2 … AN
    a1 b1
    :
    aN−1 bN−1
    2≦N≦105
    1≦ai,bi≦N
    0≦Ai≦109
    The given graph is a tree.

    Output

    If it is possible to remove all the stones from the vertices, print YES. Otherwise, print NO.

    Sample Input

    5
    1 2 1 1 2
    2 4
    5 2
    3 2
    1 3

    Sample Output

    YES

    Hint

    题意

    给你一棵树,你每次可以选择两个叶子节点,使得这条路径上的所有点的点权减1,问你能否全部变成0.

    题解:

    考虑只有一层的时候,即一个点和一堆叶子,需要满足哪些条件,才能使得所有叶子节点的权值为0呢:

    1.叶子权值和一定要大于等于父亲节点的权值,因为这样父亲节点才能满足下面的叶子节点的消耗。

    2.叶子权值和的两倍要小于等于父亲节点的权值,因为叶子节点的权值每次是-2的,而父亲节点是-1.

    3.叶子权值的最大值应该小于等于父亲节点。

    根据这三个规则,一直递归的使得底层的点处理完之后,等价的看为叶子节点,然后不停跑就好了,有点树形dp的感觉……

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5+6;
    int n,a[maxn];
    vector<int> E[maxn];
    void dfs(int x,int p){
        if(E[x].size() == 1)return;
        long long sum = 0;
        long long mx = 0;
        for(int i=0;i<E[x].size();i++){
            int v = E[x][i];
            if(v==p)continue;
            dfs(v, x);
            sum += a[v];
            mx = max(1ll*a[v], mx);
        }
        if(a[x]>sum||sum>2*a[x]){
            cout<<"NO"<<endl;
            exit(0);
        }
        int k=sum-a[x];
        if(k>sum-mx){
            cout<<"NO"<<endl;
            exit(0);
        }
        a[x]-=k;
    }
    int main()
    {
        scanf("%d", &n);
        for(int i=0;i<n;i++)
            scanf("%d", &a[i]);
        for(int i=1;i<n;i++){
            int x,y;
            scanf("%d%d", &x, &y);
            x--,y--;
            E[x].push_back(y);
            E[y].push_back(x);
        }
        if(n==2){
            if(a[0]==a[1])puts("YES");
            else puts("NO");
            return 0;
        }
        int v=0;
        while(E[v].size() == 1) v++;
        dfs(v, -1);
        if(a[v]==0)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
  • 相关阅读:
    【NLP_Stanford课堂】最小编辑距离
    【NLP_Stanford课堂】句子切分
    【NLP_Stanford课堂】词形规范化
    【NLP_Stanford课堂】分词
    【NLP_Stanford课堂】正则表达式
    【Python自然语言处理】第一章学习笔记——搜索文本、计数统计和字符串链表
    【C++ Primer】详解C++和C中的float中的有效数字
    【C++ Primer】读书笔记_第一章
    【SQL Server 2012】按倒序存储“分组统计”结果的临时表到新建表
    Git学习
  • 原文地址:https://www.cnblogs.com/qscqesze/p/6366606.html
Copyright © 2011-2022 走看看