zoukankan      html  css  js  c++  java
  • 喵哈哈村的卢西奥

    为了拯救喵哈哈村,这个世界必须要存在英雄。

    一名叫做卢西奥的英雄站了出来!他现在面临一个难题:

    他被要求将一棵树拆成3份,使得每一份中所有节点的权值和相等。

    他希望知道,对于一棵给定的有根树,在选取其中2个非根节点并将它们与它们的父亲节点分开后,所形成的三棵子树的节点权值之和能够两两相等的方案有多少种。

    两种方案被看做不同的方案,当且仅当形成方案的2个节点不完全相同。

    每个输入文件包含多组输入,在输入的第一行为一个整数T,表示数据的组数。

    每组输入的第一行为一个整数N,表示给出的这棵树的节点数。

    接下来N行,依次描述结点1~N,其中第i行为两个整数Vi和Pi,分别描述这个节点的权值和其父亲节点的编号。

    父亲节点编号为0的节点为这棵树的根节点。

    满足3<=N<=100000, |Vi|<=100, T<=10

    对于每组输入,输出一行Ans,表示方案的数量。


    2
    3
    1 0
    1 1
    1 2
    4
    1 0
    1 1
    1 2
    1 3
    1
    0
    题解

    两种情况:

    第一种情况,有两个是子树,这个东西用启发式合并/dp去维护一下当前sz[x]=all/3的个数就好了。

    第二种情况,只有一个是子树,那么第二段显然是包含了第一段的,那么就存在一个的size=2all/3,一个sz=all/3的情况,统计一下就好了。

    dfs处理一下就好了,具体看代码:

    #include<bits/stdc++.h>
    // #include <unordered_set>
    
    using namespace std;
    
    #define FF first
    #define SS second
    #define MP make_pair
    #define PB push_back
    #define lson rt << 1, l, mid
    #define rson rt << 1 | 1, mid + 1, r
    #define FOR(i, n, m) for(int i = n; i <= m; i++)
    #define REP(i, n, m) for(int i = n; i >= m; i--)
    #define ll long long
    
    typedef long long LL;
    typedef pair<int,int> PII;
    typedef pair<LL, LL> PLL;
    typedef unsigned long long ULL;
    
    /****************************define***************************************/
    const int mod = 1e9 + 7;
    const int maxn = 100010;
    
    
    int n;
    int v[maxn], sz[maxn], p[maxn];
    vector<int> nd[maxn];
    int s;
    int cn = 0, cn2 = 0;
    ll ans = 0;
    
    void Dfs_sz(int u){
            sz[u] += v[u];
            int t = nd[u].size();
            FOR(i, 0, t-1) {
                Dfs_sz(nd[u][i]);
                sz[u] += sz[nd[u][i]];
                }
            }
    void Dfs(int u){
            //printf("node %d. ans %d. cn %d. cn2 %d. sz %d
    ", u, ans, cn, cn2, sz[u]);
            if(sz[u] == s/3) {
                ans += cn + cn2;
                //printf("node %d. ans %d
    ", u, ans);
                }
            if(p[u] != 0 && sz[u] == s*2/3) cn2++;
            int t = nd[u].size();
            FOR(i, 0, t-1){
                Dfs(nd[u][i]);
                }
            if(sz[u] == s/3) cn++;
            if(p[u] != 0 && sz[u] == s*2/3) cn2--;
            }
    
    int main(){
            int t;
            cin >> t;
            while(t--){
                cn = 0, cn2 = 0;
                s = 0, ans = 0;
                FOR(i, 0, maxn-1) nd[i].clear();
                memset(sz, 0, sizeof(sz));
    
                int n, root=-1;
                cin >> n;
                FOR(i, 1, n) {
                    cin >> v[i] >> p[i];
                    s += v[i];
                    nd[p[i]].PB(i);
                    if(p[i] == 0) root=i;
                    }
                if(s % 3 != 0) cout << 0 << endl;
                else{
                    Dfs_sz(root);
                    Dfs(root);
                    printf("%lld
    ", ans);
                    }
                }
            return 0;
            }
     
  • 相关阅读:
    js-高级06-正则
    js-高级05-javaScript处理机制
    js-高级04-函数高级应用
    js-高级03-面向对象的继承
    js-高级02-贪吃蛇案例分析
    js-高级01面向对象及创建对象
    js-API 06 高级动画二
    js-API 05 高级动画
    对象数组 数组对象 增删改查 数组
    jQuery ajax请求 一般请求和自定义请求
  • 原文地址:https://www.cnblogs.com/gfdybz/p/6558850.html
Copyright © 2011-2022 走看看