|
| 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