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

C. Garland

链接:

http://codeforces.com/contest/767/problem/C

题意:

给你一颗树,其中包含N个点,让你将这颗树剪去两条边,使得变成三部分,要求三部分的权值和相等。

题解:

1、我们设定sum【i】表示以i作为根的子树权值和。

那么过程维护,sum【i】+=sum【v】;

2、如果全部点的权值和不是3的倍数,那么显然无解,否则考虑:

①遇到了一个点u,此时sum【u】=tot/3;那么这个点就可以将其拆除出来。

②将一个点拆出来的同时,设定sum【u】=0;回溯,继续找下一个tot/3

③如果过程中遇到了两个sum【u】=tot;此时存在解。

代码:

 1 #include <map>
 2 #include <set>
 3 #include <cmath>
 4 #include <queue>
 5 #include <stack>
 6 #include <cstdio>
 7 #include <string>
 8 #include <vector>
 9 #include <cstring>
10 #include <iostream>
11 #include <algorithm>
12 #include <functional>
13 using namespace std;
14 #define rep(i,a,n) for (int i=a;i<=n;i++)
15 #define per(i,a,n) for (int i=n;i>=a;i--)
16 #define pb push_back
17 #define mp make_pair
18 #define all(x) (x).begin(),(x).end()
19 #define fi first
20 #define se second
21 #define SZ(x) ((int)(x).size())
22 typedef vector<int> VI;
23 typedef long long ll;
24 typedef pair<int, int> PII;
25 const ll mod = 1000000007;
26 // head
27 
28 const int maxn = 1e6 + 7;
29 VI tree[maxn];
30 int val[maxn];
31 int sum[maxn];
32 int n, tot, ans1, ans2, root;
33 
34 void dfs(int u)
35 {
36     sum[u] = val[u];
37     for (int i = 0; i<tree[u].size(); i++){
38         int v = tree[u][i];
39         dfs(v);
40         sum[u] += sum[v];
41     }
42     if (sum[u] == tot){
43         if (u == root) return;
44         if (ans1 == -1){
45             ans1 = u;
46             sum[u] = 0;
47         }
48         else if (ans2 == -1){
49             ans2 = u;
50             sum[u] = 0;
51         }
52     }
53 }
54 
55 int main()
56 {
57     cin >> n;
58     rep(i, 1, n) {
59         int a;
60         scanf("%d%d", &a, val + i);
61         tot += val[i];
62         if (a == 0) {
63             root = i; 
64             continue;
65         }
66         tree[a].pb(i);
67     }
68     if (tot % 3) return 0 * printf("-1\n");
69     tot /= 3;
70     ans1 = ans2 = -1;
71     dfs(root);
72     if (ans1 == -1 || ans2 == -1) cout << -1 << endl;
73     else cout << ans1 << " " << ans2 << endl;
74     return 0;
75 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值