• AGC010C Cleaning


    Description

    传送门


    Solution

    考虑对于每个点处理它的所有儿子,它的所有儿子连上来的路径要不就是在当前子树内两两匹配,要不就是继续连到该点的父亲。

    如果在子树内匹配,儿子两个儿子的石子数量减一,该节点的石子数量减一;对于连上去的,某个儿子的石子数量减一,该节点的石子数量减一。

    所以设某节点处理完子树之后还要往父亲连(f_x)条路径,有(y)条路径在它的子树内互相匹配,它的子树内一共有(sum)条路径,它本身权值为(a_x),那么有

    [y imes 2 + f_x = sum ]

    [y + f_x = a_x ]

    解得

    [y = sum - a_x, f_x = sum - 2 imes y ]

    首先连上去的路径个数肯定不能超过它本身的权值(a_x),即(f_x <= a_x);也不能是负数,即(f_x >= 0)

    其次它的子树内部最多的两两互相匹配的路径个数要比需要的两两匹配的路径条数多,而这个最大值就是(max(frac{sum}{2}, sum - max_{f_v})),首先两两匹配最多就是(frac{sum}{2}),其次每个点不能和自己匹配所以还要和(sum - max_{f_v})取较小值。

    注意(f_{root})必须是零,因为根节点不能再往上传递了。

    注意到(n = 2)两个点都是叶子节点要特判。


    Code

    /*
        _______                       ________                        _______
       / _____                      / ______                       / _____ 
      / /     \_  _     __     _   / /          _     __     _   / /     \_
     | |          | |   |  |   | | | |        | | | |   |  |   | | | |
     | |          | |   |  |   | | | |     __ | | | |   |  |   | | | |
     | |       __     |  |  /  / | |      | |     |  |  /  / | |       __
       \_____/ /    / / /  /    \_____  /     / / /  /    \_____/ /
       \_______/    \___/  \___/     \______/\__   \___/  \___/     \_______/
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int N = 1e5;
    
    int head[N + 50], num, a[N + 50], f[N + 50], n, root, in[N + 50], flag = 1;
    
    struct Node{
    	int next, to;
    } edge[N * 2 + 50];
    
    void Addedge(int u, int v){
    	edge[++num] = (Node){head[u], v};
    	head[u] = num;
    	return;
    }
    
    void Dfs(int x, int fa){
    	if (in[x] == 1) { f[x] = a[x]; return; }
    	int sum = 0, maxx = 0;
    	for (int i = head[x]; i && flag; i = edge[i].next){
    		int v = edge[i].to;
    		if (v == fa) continue;
    		Dfs(v, x);
    		sum += f[v]; maxx = max(maxx, f[v]);
    	} 
    	if (!flag) return;
    	int y = sum - a[x];
    	f[x] = sum - y * 2;
    	if (f[x] > a[x]) { flag = 0; return; }
    	if (min(sum / 2, sum - maxx) < y) { flag = 0; return; }
    	if (x == root && f[x] != 0) { flag = 0; return; } 
    }
    
    void Read(int &x)
    {
    	x = 0; int p = 0; char st = getchar();
    	while (st < '0' || st > '9') p = (st == '-'), st = getchar();
    	while (st >= '0' && st <= '9') x = (x << 1) + (x << 3) + st - '0', st = getchar();
    	x = p ? -x : x;
    	return;
    }
    
    int main()
    {
    	Read(n);
    	for (int i = 1; i <= n; i++) Read(a[i]);
    	if (n == 2){
    		if (a[1] == a[2]) puts("YES");
    		else puts("NO");
    		return 0;
    	}
    	for (int i = 1, u, v; i <= n - 1; i++) Read(u), Read(v), Addedge(u, v), Addedge(v, u), in[u]++, in[v]++;
    	for (int i = 1; i <= n; i++) if (in[i] > 1) { root = i; break; }
    	Dfs(root, 0);
    	puts(!flag ? "NO" : "YES");
    	return 0;
    }
    
  • 相关阅读:
    http协议基础(三)几种数据传输方式
    http协议基础(二)请求和响应报文的构成
    http协议(一)基础知识
    性能测试常见术语浅析
    TPS和QPS定义以及影响TPS的因素
    JMeterPlugin性能监控
    jmeter压测之 监控--nmon
    对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB)
    C# AES的128位、192位、256位加密
    C# 处理base64 以及base64的原理分析
  • 原文地址:https://www.cnblogs.com/Tian-Xing-Sakura/p/13961220.html
Copyright © 2020-2023  润新知