-
Notifications
You must be signed in to change notification settings - Fork 50
/
Copy path110E. Lucky Tree.cpp
84 lines (69 loc) · 1.58 KB
/
110E. Lucky Tree.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/*
Idea:
- Count the number of nodes in each node subtree such that there is a
lucky edge in the path between them.
- Count the number of nodes for each node outside the subtree of it
such that there is a lucky edge in the path between them.
- Use the information from the previous steps to calculate the answer.
*/
#include <bits/stdc++.h>
using namespace std;
int const N = 1e5 + 1;
bool vis[N];
int n, f[N], ff[N], siz[N];
vector<vector<pair<int, int> > > g;
bool is_lucky(int x) {
while(x != 0) {
if(x % 10 != 4 && x % 10 != 7)
return false;
x /= 10;
}
return true;
}
void DFS1(int u) {
vis[u] = true;
++siz[u];
for(int i = 0, v; i < g[u].size(); ++i) {
v = g[u][i].first;
if(!vis[v]) {
DFS1(v);
siz[u] += siz[v];
if(is_lucky(g[u][i].second))
f[u] += siz[v];
else
f[u] += f[v];
}
}
}
void DFS2(int u) {
vis[u] = true;
for(int i = 0, v; i < g[u].size(); ++i) {
v = g[u][i].first;
if(!vis[v]) {
if(is_lucky(g[u][i].second))
ff[v] = n - siz[v];
else
ff[v] = ff[u] + f[u] - f[v];
DFS2(v);
}
}
}
int main() {
scanf("%d", &n);
g.resize(n);
for(int i = 0, a, b, c; i < n - 1; ++i) {
scanf("%d %d %d", &a, &b, &c);
--a, --b;
g[a].push_back({b, c});
swap(a, b);
g[a].push_back({b, c});
}
DFS1(0);
memset(vis, false, sizeof vis);
DFS2(0);
long long res = 0;
for(int i = 0; i < n; ++i)
res += 1ll * f[i] * (f[i] - 1) + 1ll * ff[i] * (ff[i] - 1) + 2ll * f[i] * ff[i];
printf("%lld\n", res);
return 0;
}