题意
传送门 LeeCode 1617. 统计子树中城市之间最大距离
题解
考虑到节点数较少,进行状态压缩然后 O ( 2 n ) O(2^n) O(2n) 枚举子集。问题在于如何判断子集对应的节点恰好构成一颗子树,可以 D F S DFS DFS 求解,每次只向在同一个子集中的节点搜索,将状态对应二进制位赋 0 0 0,那么假如子集恰好对应一颗子树,则 D F S DFS DFS 结束时状态为 0 0 0。子树的最大路径可以在 D F S DFS DFS 的同时求解,对于每一个节点,最大路径的可能值为与根节点的路径或子树中最大的两条路径和。总复杂度 O ( n 2 n ) O(n2^n) O(n2n)。
class Solution
{
#define maxn 17
public:
vector<int> G[maxn];
int dfs(int p, int v, int d, int &s, int &mx)
{
int m1 = 0, m2 = 0;
for (int i = 0; i < G[v].size(); i++)
{
int u = G[v][i];
if (u != p && (s >> u & 1))
{
int t = dfs(v, u, d + 1, s, mx);
if (t > m1) swap(t, m1);
if (t > m2) swap(t, m2);
}
}
s ^= 1 << v, mx = max(mx, max(d, m1 + m2));
return m1 + 1;
}
vector<int> countSubgraphsForEachDiameter(int n, vector<vector<int>> &edges)
{
for (auto e : edges)
{
int u = e[0] - 1, v = e[1] - 1;
G[u].push_back(v);
G[v].push_back(u);
}
vector<int> res(n - 1);
for (int s = 0; s < (1 << n); s++)
{
for (int i = 0; i < n; i++)
{
if (s >> i & 1)
{
int t = s, mx = 0;
dfs(-1, i, 0, t, mx);
if (!t && mx > 0)
{
++res[mx - 1];
}
break;
}
}
}
return res;
}
};