Skip to content

Commit 75b9cc9

Browse files
authored
Create count-subtrees-with-max-distance-between-cities.cpp
1 parent f0703c2 commit 75b9cc9

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Time: O(n^5)
2+
// Space: O(n^3)
3+
4+
class Solution {
5+
public:
6+
vector<int> countSubgraphsForEachDiameter(int n, vector<vector<int>>& edges) {
7+
vector<vector<int>> adj(n);
8+
for (const auto& edge : edges) {
9+
int u = edge[0] - 1, v = edge[1] - 1;
10+
adj[u].emplace_back(v);
11+
adj[v].emplace_back(u);
12+
}
13+
vector<int> lookup(n), result(n - 1);
14+
for (int i = 0; i < n; ++i) {
15+
vector<vector<vector<int>>> dp(n, vector<vector<int>>(n, vector<int>(n)));
16+
vector<int> count(n, 1);
17+
dfs(n, adj, i, -1, lookup, &count, &dp);
18+
lookup[i] = 1;
19+
for (int d = 1; d <= n - 1; ++d) {
20+
for (int max_d = 1; max_d <= n - 1; ++max_d) {
21+
result[max_d - 1] += dp[i][d][max_d];
22+
}
23+
}
24+
}
25+
return result;
26+
}
27+
28+
private:
29+
void dfs(int n, const vector<vector<int>>& adj,
30+
int curr, int parent,
31+
const vector<int>& lookup,
32+
vector<int> *count,
33+
vector<vector<vector<int>>> *dp) {
34+
35+
vector<int> children;
36+
for (const auto& child : adj[curr]) {
37+
if (child == parent || lookup[child]) {
38+
continue;
39+
}
40+
dfs(n, adj, child, curr, lookup, count, dp);
41+
children.emplace_back(child);
42+
}
43+
for (const auto& child : children) {
44+
vector<vector<int>> new_dp_curr = (*dp)[curr];
45+
for (int d = 0; d < (*count)[child]; ++d) {
46+
for (int max_d = 0; max_d < (*count)[child]; ++max_d) {
47+
new_dp_curr[d + 1][max(max_d, d + 1)] += (*dp)[child][d][max_d];
48+
}
49+
}
50+
for (int curr_d = 0; curr_d < (*count)[curr]; ++curr_d) {
51+
for (int curr_max_d = 0; curr_max_d < (*count)[curr]; ++curr_max_d) {
52+
if (!(*dp)[curr][curr_d][curr_max_d]) {
53+
continue;
54+
}
55+
for (int child_d = 0; child_d < (*count)[child]; ++child_d) {
56+
for (int child_max_d = 0; child_max_d < (*count)[child]; ++child_max_d) {
57+
int max_d = max({curr_max_d, child_max_d, curr_d + child_d + 1});
58+
if (max_d < size(new_dp_curr[max(curr_d, child_d + 1)]))
59+
new_dp_curr[max(curr_d, child_d + 1)][max_d] += (*dp)[curr][curr_d][curr_max_d] * (*dp)[child][child_d][child_max_d];
60+
}
61+
}
62+
}
63+
}
64+
(*dp)[curr] = move(new_dp_curr);
65+
(*count)[curr] += (*count)[child];
66+
}
67+
(*dp)[curr][0][0] = 1;
68+
}
69+
};
70+
71+
72+
// Time: O(n * 2^n)
73+
// Space: O(n)
74+
class Solution2 {
75+
public:
76+
vector<int> countSubgraphsForEachDiameter(int n, vector<vector<int>>& edges) {
77+
vector<vector<int>> adj(n);
78+
for (const auto& edge : edges) {
79+
int u = edge[0] - 1, v = edge[1] - 1;
80+
adj[u].emplace_back(v);
81+
adj[v].emplace_back(u);
82+
}
83+
vector<int> result(n - 1);
84+
int total = 1 << n;
85+
for (int mask = 1; mask < total; ++mask) {
86+
int d = maxDistance(n, edges, adj, mask);
87+
if (d - 1 >= 0) {
88+
++result[d - 1];
89+
}
90+
}
91+
return result;
92+
}
93+
94+
private:
95+
int maxDistance(int n,
96+
const vector<vector<int>>& edges,
97+
const vector<vector<int>>& adj,
98+
int mask) {
99+
const auto& [is_valid, farthest, max_d] = bfs(n, adj, mask, log(mask & -mask) / log(2));
100+
return is_valid ? get<2>(bfs(n, adj, mask, farthest)) : 0;
101+
}
102+
103+
tuple<bool, int, int> bfs(int n, const vector<vector<int>>& adj,
104+
int mask, int start) {
105+
queue<pair<int, int>> q({{start, 0}});
106+
int lookup = (1 << start);
107+
int count = __builtin_popcount(mask) - 1, u = -1, d = -1;
108+
while (!empty(q)) {
109+
tie(u, d) = move(q.front()); q.pop();
110+
for (const auto& v : adj[u]) {
111+
if (!(mask & (1 << v)) || (lookup & (1 << v))) {
112+
continue;
113+
}
114+
lookup |= (1 << v);
115+
--count;
116+
q.emplace(v, d + 1);
117+
}
118+
}
119+
return {count == 0, u, d};
120+
}
121+
};

0 commit comments

Comments
 (0)