zoukankan      html  css  js  c++  java
  • AtCoder Grand Contest 010 --C:Cleaning

    Cleaning

    时间限制: 2 Sec 内存限制: 256 MB

    题目描述

    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.

    Constraints
    2≤N≤105
    1≤ai,bi≤N
    0≤Ai≤109
    The given graph is a tree.

    输入

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

    N
    A1 A2 … AN
    a1 b1
    :
    aN−1 bN−1

    输出

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

    样例输入

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

    样例输出

    YES
    

    提示
    All the stones can be removed, as follows:

    Select vertices 4 and 5. Then, there is one stone remaining on each vertex except 4.
    Select vertices 1 and 5. Then, there is no stone on any vertex.

    分析

    对于每颗子树,该子树的根上的石头有两种消去方式:

    • 选择两个子树内部的叶子
    • 选择一个子树中的叶子和子树外部的叶子

    我们假设通过第一种方式消去的根的石头数为(p),那么第二种方式消去数应为 (A[root]-p)。根消去(p)时,这个根的儿子应当总共消去(2p),消去后应满足式子$$sum-2p=A[root]-p$$所以(p=sum-A[root]),这样操作一次之后就可以把子树等价为还有(A[root]-p)个石头的叶子。

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <vector>
    #include <map>
    using namespace std;
    const int maxn=200050;
    typedef long long ll;
    struct Edge
    {
        int v,nxt;
    }e[maxn*2];
    int h[maxn],tot;
    void addEdge(int x,int y){
        e[++tot]=(Edge){y,h[x]};
        h[x]=tot;
    }
     
    ll w[maxn];
    bool ans=true;
    ll dfs(int x,int x_fa){
        ll sum=0,cnt=0,M=0;
        for (int i = h[x]; i ; i=e[i].nxt)
        {
            if(e[i].v!=x_fa){
                ll t=dfs(e[i].v,x);
                sum+=t;
                M=max(M,t);
                cnt++;
            }
        }
        if(cnt==0) return w[x];
        if(cnt==1){
            if(sum!=w[x]) ans=false;
            return sum;
        }
        ll p=sum-w[x];
        if(p<0||w[x]<p||sum-M<p) ans=false;
        return w[x]-p;
    }
    int deg[maxn];
    int main(int argc, char const *argv[])
    {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i)
        {
            scanf("%lld", w+i);
        }
        for (int i = 0; i < n-1; ++i)
        {
            int x,y;
            scanf("%d%d", &x,&y);
            addEdge(x,y);
            addEdge(y,x);
            deg[x]++;
            deg[y]++;
        }
        if(n==1){
            printf("%s
    ", w[1]?"NO":"YES");
            return 0;
        }
        if(n==2){
            printf("%s
    ", w[1]==w[2]?"YES":"NO");
            return 0;
        }
        int root=1;
        for (int i = 1; i <= n; ++i)
        {
            if(deg[i]>1) root=i;
        }
        if(dfs(root,root)!=0) ans=false;
        if(ans) printf("YES
    ");
        else printf("NO
    ");
        return 0;
    }
    
  • 相关阅读:
    Android学习(九) SharedPreferences
    Android学习(八) 打开Activity
    Android学习(七) Android实现计算器
    Android学习(六) 文本框边框
    Android学习(五) 圆角实现(转)
    Android学习(四) Layout五大布局
    Android学习(三) 自动完成的使用
    SQL Server中的三种物理连接操作
    ASP.NET实现大文件下载
    ASP.NET上传大文件的问题
  • 原文地址:https://www.cnblogs.com/sciorz/p/8900563.html
Copyright © 2011-2022 走看看