Codeforces Round #398 (Div. 2) C. Garland (dfs)

版权声明:希望能在自己成长的道路上帮到更多的人,欢迎各位评论交流 https://blog.csdn.net/yiqzq/article/details/82145789

原题地址:http://codeforces.com/contest/767/problem/C

题意:给出一棵树,每个节点有一个权值,现在要将节点分成3份,使得每一份权值都相同.

思路:一开始直接dfs从根节点开始搜索,然后WA在了第9组样例,看了大佬的解释才知道,由于负数的存在,使得从根节点开始是行不通的,正确的做法应该是从最低从开始判断.

大佬的说法:就是一个点加和与它其中一个子树的加和相同,但是总加和的1/3不为0(不理解的可以试一下这组数据 5 0 3 1 1 1 0 2 2 3 3,自己画一下)

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e6 + 5;
const int mod = 1e9 + 7;
struct node {
    int v, nxt;
} e[maxn << 1];
int tot, head[maxn];
void init_head() {
    tot = 0;
    CLR(head, -1);
}
void add_edge(int u, int v) {
    e[tot].v = v;
    e[tot].nxt = head[u];
    head[u] = tot++;
}
vector<int>v;
int tmp[maxn], n, root;
int sum, half, num;
int  dfs1(int u, int fa) {
    for (int i = head[u]; ~i; i = e[i].nxt) {
        int v = e[i].v;
        if (v == fa) continue;
        tmp[u] += dfs1(v, u);
    }
    /*
    要从底层开始判,不然的话,由于负数的存在,会有错
    */
    if (tmp[u] == half && u != root) {//不能是根节点
        v.push_back(u);
        tmp[u] = 0;
    }
    return tmp[u];
}

int main() {
    init_head();
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        if (u == 0) {
            root = i;
        } else {
            add_edge(i, u);
            add_edge(u, i);
        }
        tmp[i] = v;
        sum += v;
    }
    if (sum % 3) {//如果总和不能整除3,那么就一定不能成功
        printf("-1\n");
        return 0;
    }
    half = sum / 3;
    dfs1(root, -1);
    if (v.size() < 2) printf("-1\n");//如果成功的节点少于2个,那么就是-1
    else printf("%d %d\n", v[0], v[1]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/82145789
今日推荐