Codeforces348B Apple Tree DFS

题意:一颗苹果树上每个叶子结点苹果个数不同,现在需要从苹果树上取下最少的苹果,使得对于每一个结点,他的所有子树的苹果个数相同。

两遍dfs。

对于两颗子树,如果第一颗子树有四个结点,第二棵子树有五棵结点,又因为第一棵子树的权值等于第二棵子树的权值,所以说,两颗树的权值一定是  4 的倍数且是5的倍数,所以每棵子树都是20的倍数。深入理解一下这个意思,我们可以得到这样的结论,对于第一棵树,它转化为20个兄弟,并排着,第二棵树可以变成20个兄弟并排着,那么对于这两棵树的父亲可以变成40个结点并排。然后,来想一下,第一棵树的四个儿子,显然,每个儿子必然是5的倍数,所以每个儿子可以变成五份,这和第一个结点变成20份等价。

现在解决这棵子树能分成多少份,下面就来解决,每个份 最大是多少,显然,对于每个叶子结点 L = min(L,叶子结点权值V / 叶子结点应该被分成NUM份)

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstdio>
 4 #include <cstdlib>
 5 using namespace std;
 6 long long a[1111111];
 7 long long s[1111111];
 8 long long S;
 9 long long L = 1e15;
10 long long ans = 0;
11     int N;
12 vector<int> E[1111111];
13 long long gcd(long long x,long long y)
14 {
15     return y==0?x:gcd(y,x%y);
16 }
17 long long lca(long long x,long  long y)
18 {
19     return x*(y/gcd(x,y));
20 }
21 long long dfs(int u,int p)
22 {
23     if (E[u].size()==1&&u!=1)
24     {
25         s[u] = a[u];
26         return 1LL;
27     }
28     long long num = 1;
29     for (int i =0 ;i<E[u].size(); i++)
30     {
31         if (E[u][i]==p) continue;
32         num = lca(num,dfs(E[u][i],u));
33         s[u] += s[E[u][i]];
34     }
35     if ((E[u].size()-(u==1?0:1))*num >= S) {cout << S <<endl;exit(0);}
36     return (E[u].size()-(u==1?0:1))*num;
37 }
38 void dfs2(int u,int p,long long num)
39 {
40     if (E[u].size()==1&&u!=1)
41     {
42         L = min(L,s[u]/num);
43     }
44     for (int i =0 ;i<E[u].size(); i++)
45     {
46         if (E[u][i]==p) continue;
47         dfs2(E[u][i],u,num/(E[u].size()-(u==1?0:1)));
48     }
49 }
50 int main()
51 {
52
53     //freopen("in.txt","r",stdin);
54     cin >> N;
55     for (int i = 1; i<=N; i++)
56     {
57          scanf("%I64d",&a[i]);
58          S+=a[i];
59     }
60     for (int i = 1; i<N ; i++)
61     {
62         int x,y;
63         scanf("%d%d",&x,&y);
64         E[x].push_back(y);
65         E[y].push_back(x);
66     }
67     long long dd = dfs(1,0);
68     dfs2(1,0,dd);
69     if (dd * L >= S)
70     {
71         cout <<0<<endl;
72     }
73     else
74     {
75         cout << S-dd*L<<endl;
76     }
77     return 0;
78 }

时间: 2024-11-10 03:58:38

Codeforces348B Apple Tree DFS的相关文章

【POJ 3321】 Apple Tree (dfs重标号设区间+树状数组求和)

[POJ 3321] Apple Tree (dfs重标号设区间+树状数组求和) Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 21966   Accepted: 6654 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. K

[poj3321]Apple Tree(dfs序+树状数组)

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 26762   Accepted: 7947 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been

POJ3321 - Apple Tree DFS序 + 线段树或树状数组

Apple Tree:http://poj.org/problem?id=3321 题意: 告诉你一棵树,每棵树开始每个点上都有一个苹果,有两种操作,一种是计算以x为根的树上有几个苹果,一种是转换x这个点上的苹果,就是有就去掉,没有就加上. 思路: 先对树求一遍dfs序,每个点保存一个l,r.l是最早到这个点的时间戳,r是这个点子树中的最大时间戳,这样就转化为区间问题,可以用树状数组,或线段树维护区间的和. #include <algorithm> #include <iterator&

POJ 3321 Apple Tree DFS序+fenwick

题目大意:有一颗长满苹果的苹果树,有两个操作. 1.询问以一个点为根的子树中有多少个苹果. 2.看看一个点有没有苹果,假设没有苹果.那么那里就立即长出一个苹果(= =!):否则就把那个苹果摘下来. 思路:进行一次深搜,将每一个节点最開始出现的时间和最后出现的时间记在一个数组里,那么这两点之间的点就是它以及它的子树的二倍,然后就用树状数组来维护区间和即可了. CODE: #include <cstdio> #include <cstring> #include <iostrea

POJ 3321 Apple Tree DFS序 + 树状数组

多次修改一棵树节点的值,或者询问当前这个节点的子树所有节点权值总和. 首先预处理出DFS序L[i]和R[i] 把问题转化为区间查询总和问题.单点修改,区间查询,树状数组即可. 注意修改的时候也要按照dfs序修改,因为你查询就是按照dfs查的,所以修改也要用dfs序修改 L[i]是唯一的. #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <

POJ-3321 Apple Tree 【DFS序+树状数组】

Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been carefully nurturing the big apple tree. The tree has N forks which are connected by branches.

POJ 3321 Apple Tree (dfs+线段树)

题目大意: 修改树上的节点,然后求子树的和. 思路分析: dfs 重新编号,烂大街了... #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #define maxn 100005 #define lson num<<1,s,mid #define rson num<<1|1,mid+1,e using namespace std

Apple Tree POJ - 3321 dfs序列构造树状数组(好题)

There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been carefully nurturing the big apple tree. The tree has N forks which are connected by branches. Kaka numbers

线段树+dfs序(Apple Tree )(Assign the task )

线段树+dfs序 给定一棵n个节点的树,m次查询,每次查询需要求出某个节点深度为h的所有子节点. 作为预处理,首先将树的所有节点按深度保存起来,每个深度的所有节点用一个线性结构保存,每个深度的节点相对顺序要和前序遍历一致. 然后从树的根节点进行dfs,对于每个节点记录两个信息,一个是dfs进入该节点的时间戳in[id],另一个是dfs离开该节点的时间戳out[id]. 最后对于每次查询,求节点v在深度h的所有子节点,只需将深度为h并且dfs进入时间戳在in[v]和out[v]之间的所有节点都求出