-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprincess_presents.cpp
More file actions
179 lines (156 loc) · 5.06 KB
/
princess_presents.cpp
File metadata and controls
179 lines (156 loc) · 5.06 KB
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define fi first
#define se second
#define FOR(i,n) for(int (i)=0;(i)<(n);++(i))
typedef long long ll;
const int INF = 1e9;
const int MOD = 1e9+7;
const int N = 1e5;
const int T = 5;
vector<pii> g[N];
/* just for //asserting if graph is connected */
bool visited[N];
void dfs_connected(int v, int parent) {
visited[v] = 1;
for (auto edge : g[v]) {
int u = edge.fi;
if (u == parent) continue;
dfs_connected(u, v);
}
}
//////////////////// CASE k > 0 //////////////////////////////////////////////////
//cnt_special[v] denotes the number of special edges in v's subtree in a rooted tree
int cnt_special[N];
//cnt_subtree[v] denotes the number of subtrees of v's subtree in a rooted tree containing v (so, like hanging down from v)
ll cnt_subtree[N];
void dfs_special(int v, int p)
{
for (auto edge : g[v]) //this should be node instead of edge
{
int u = edge.fi;
if (u == p) continue;
int special = edge.se;
if (special) cnt_special[v]++;
dfs_special(u, v);
cnt_special[v] += cnt_special[u];
}
}
void dfs_subtrees(int v, int p)
{
cnt_subtree[v] = 1;
for (auto edge : g[v]) {
int u = edge.fi;
if (u == p) continue;
dfs_subtrees(u, v);
cnt_subtree[v] *= (1 + cnt_subtree[u]); //do not take any u's subtree or take any u's subtree
cnt_subtree[v] %= MOD;// the case of subtree is same as the include case because you always have to
// include the root from where you are counting the subtree
}
}
ll res = 1;
void dfs_solve(int v, int p)
{
if (cnt_special[v] == 0) // if this does not contain any special edges (fall outside blue region)
{
res *= cnt_subtree[v]; // multiply the result by the no. of subtrees it has
res %= MOD;
return;
}
for (auto edge : g[v]) // falls inside blue region
{
int u = edge.fi;
if (u == p) continue;
bool special = edge.se;
if (cnt_special[u] > 0) // if it has some special node in its subtree than we find the node that
dfs_solve(u, v); // has no special nodes in its subtree (last node of the blue region)
else
{
if (special) // if this is the special node
{
res *= cnt_subtree[u]; // we always have to take this into consideration, all of its subtrees
res %= MOD; // will be multiplied
}
else
{
res *= (1 + cnt_subtree[u]); // if this is not the special node then we can either leave it or
res %= MOD; // take its subtress
}
}
}
}
//////////////////// CASE k = 0 //////////////////////////////////////////////////
ll dp_include[N]; //dp_include[v] := number of subgraphs of v's subtree in a rooted tree containing v
ll dp_exclude[N]; //dp_exclude[v] := number of subgraphs of v's subtree in a rooted tree NOT containing v
void dfs_solve_k0(int v, int parent)
{
dp_include[v] = 1;
dp_exclude[v] = 0;
for (pii edge : g[v])
{
int u = edge.fi;
if (u == parent) continue;
dfs_solve_k0(u, v);
dp_include[v] *= (1 + dp_include[u]);
dp_include[v] %= MOD;
dp_exclude[v] += (dp_include[u] + dp_exclude[u]);
dp_exclude[v] %= MOD;
}
}
int main()
{
int t;
cin >> t;
//assert(t >= 1 && t <= T);
while (t--) {
int n;
cin >> n;
//assert(n >= 2 && n <= N);
int k = 0;
int R = -1;
FOR(i, n) //clearing everything
{
g[i].clear();
visited[i] = 0;
cnt_special[i] = 0;
cnt_subtree[i] = 0;
dp_exclude[i] = 0;
dp_include[i] = 0;
res = 1;
}
FOR(i, n-1)
{
int v, u;
bool special;
cin >> v >> u >> special;
--v, --u;
g[v].push_back(make_pair(u,special)); // graph in addition to containing the node it is connected to
//also contains whether that node is special or not
g[u].push_back(make_pair(v,special));
if (special) ++k;
if (special && k == 1) //if this is the first special node then it is the root
R = v;
}
//assert (k >= 0);
dfs_connected(0, -1); //perform dfs to check if the graph is connected or not
FOR(i, n) assert(visited[i]); //assert only fails on zero
if (k == 0)
{
//special case
int root = 0;
dfs_solve_k0(root, -1);
ll res = dp_include[root] + dp_exclude[root];
res %= MOD;
cout << res << endl;
}
else
{
dfs_special(R, -1); // gives the number of special edges starting from any node 'i'
dfs_subtrees(R, -1);// gives the total number of subtress of a node (always including it)
dfs_solve(R, -1);
cout << res << endl;
}
}
return 0;
}