CodeForces 109C 树形DP Lucky Tree

赶脚官方题解写得挺清楚的说,=_=

注意数据范围用long long,否则会溢出。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <vector>
 6 using namespace std;
 7
 8 const int maxn = 100000 + 10;
 9
10 int n;
11 vector<int> G[maxn], C[maxn];
12
13 inline int lucky(int x)
14 {
15     while(x)
16     {
17         if(x % 10 != 4 && x % 10 != 7) return 0;
18         x /= 10;
19     }
20     return 1;
21 }
22
23 long long d[maxn], sz[maxn], f[maxn];
24
25 void dfs(int u, int fa)
26 {
27     sz[u] = 1;
28     f[u] = 0;
29     for(int i = 0; i < G[u].size(); i++)
30     {
31         int v = G[u][i];
32         if(v == fa) continue;
33         dfs(v, u);
34         sz[u] += sz[v];
35         if(C[u][i]) f[u] += sz[v];
36         else f[u] += f[v];
37     }
38 }
39
40 void dfs2(int u, int fa)
41 {
42     for(int i = 0; i < G[u].size(); i++)
43     {
44         int v = G[u][i];
45         if(v == fa) continue;
46         if(C[u][i]) d[v] = sz[1] - sz[v];
47         else d[v] = d[u] + f[u] - f[v];
48         dfs2(v, u);
49     }
50 }
51
52 int main()
53 {
54     //freopen("in.txt", "r", stdin);
55
56     scanf("%d", &n);
57     for(int i = 1; i < n; i++)
58     {
59         int u, v, d; scanf("%d%d%d", &u, &v, &d);
60         int t = lucky(d);
61         G[u].push_back(v); C[u].push_back(t);
62         G[v].push_back(u); C[v].push_back(t);
63     }
64
65     dfs(1, 0);
66     dfs2(1, 0);
67
68     long long ans = 0;
69     for(int i = 1; i <= n; i++) ans += f[i] * (f[i] - 1) + d[i] * (d[i] - 1) + 2 * f[i] * d[i];
70     printf("%I64d\n", ans);
71
72     return 0;
73 }

代码君

时间: 2024-10-09 16:53:17

CodeForces 109C 树形DP Lucky Tree的相关文章

Codeforces 77C 树形dp + 贪心

题目链接:点击打开链接 题意: 给定n个点, 每个点的豆子数量 下面是一棵树 再给出起点 每走到一个点,就会把那个点的豆子吃掉一颗. 问:回到起点最多能吃掉多少颗豆子 思路:树形dp 对于当前节点u,先把子节点v都走一次. 然后再往返于(u,v) 之间,直到u点没有豆子或者v点没有豆子. dp[u] 表示u点的最大值.a[u] 是u点剩下的豆子数. #include <cstdio> #include <vector> #include <algorithm> #inc

CodeForces 274B 树形dp

//继续水一道树形dp 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "algorithm" 5 #include "cmath" 6 using namespace std; 7 __int64 dp[100010][2]; 8 bool vis[100010]; 9 int tot, first[100

codeforces 219D 树形dp

题目大意: 根据n个城市,设置n-1条有向边,希望设定一个中心城市,能通过修改一些道路的方向到达任何一座城市,希望修改的道路数量最少 输出这个最少的道路数量,并且把所有符合的可作为中心的城市编号一个个输出来 开始也实在想不出,根据树形dp,首先要确定一棵树,可是这里的边乱七八糟的,没法确定根 后来看了别人的思路,原来还是自己太死脑筋了,根本不需要确定根,可以把任意一个城市作为根来解决题目,这里假定1为根 把所有的有向边看作无向边,但要记录那条边是真实存在的,哪条是自己加的 用dp[i]表示 i

Codeforces 1088E 树形dp+思维

比赛的时候看到题意没多想就放弃了.结果最后D也没做出来,还掉分了,所以还是题目做的太少,人太菜. 回到正题: 题意:一棵树,点带权值,然后求k个子连通块,使得k个连通块内所有的点权值相加作为分子除以k的值最大,如果这样的最大值有多个,就最大化k. 赛后看了看别人的代码仔细想了一想,还是挺容易的. 首先将树分为若干个连通块,考虑一个权值求和最大的连通块,设该最大值为sum,那么其他所有的连通块,权值求和都不可能比当前的连通块大. 在不考虑最大化k的情况下,就没有必要再将其他的连通块加进来(因为如果

[动态规划][树形dp]Bichrome Tree

题目描述 We have a tree with N vertices. Vertex 1 is the root of the tree, and the parent of Vertex i (2≤i≤N) is Vertex Pi.To each vertex in the tree, Snuke will allocate a color, either black or white, and a non-negative integer weight.Snuke has a favor

Codeforces 743D 树形dp

D. Chloe and pleasant prizes 题意:一棵树,以结点1为根结点悬挂在墙上,每个点有一个权值.选两条边切断,要求:刚好掉下两份结点,且两份不能属于同一子树.求两份结点可能的最大权值和. tags:裸的树dp. #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for

codeforces 500d 树形dp和概率

求期望,公式是从树中任选3个点,共有C(n, 3)种情况,所有情况的和 / C(n, 3)即为答案. 对于树中的任意两个点,可以构成一条固定的路径,再从剩下的n - 2个点找一个点,可以得到另外两条路径,共有n - 2种情况. 所以每条路径出现的次数为n - 2次. 假设边Ei共有Ci条路径经过,则对于i = 1 : n, Wi * Ci的和即为所有路径的权和, 结果为所有路径的权和 * (n - 2) / C(n, 3); 化简得到公式:所有路径的权和 / n / (n - 1) * 6. #

HDU 5379 树形DP Mahjong tree

任意一棵子树上节点的编号连续,每个节点的所有二字节点连续,求编号方案的总数. 稍微分析一下可知 每个节点的非叶子节点个数不能多于两个,否则这个子树无解,从而整棵树都无解. 每棵子树将所有节点按照编号从小到大排序,根节点要么在最左端,要么在最右端,而且这两种情况相等.(后面会有具体分析) 设size(u)表示以节点u为根的子树中节点总数. d(u)表示用1 ~ size(u)给以u为根的子树编号的合法方案数,考虑下面几种情况: ①:  u是叶子节点,方案数为1. ②:  u的所有儿子节点都是叶子节

CodeForces 519E 树形DP A and B and Lecture Rooms

给出一棵树,有若干次询问,每次询问距两个点u, v距离相等的点的个数. 情况还挺多的,少侠不妨去看官方题解.^_^ 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 8 const int maxn = 100000 + 10; 9 10