给你 n 个城市,编号为从 1 到 n 。同时给你一个大小为 n-1 的数组 edges ,其中 edges[i] = [ui, vi] 表示城市 ui 和 vi 之间有一条双向边。题目保证任意城市之间只有唯一的一条路径。换句话说,所有城市形成了一棵 树 。
一棵 子树 是城市的一个子集,且子集中任意城市之间可以通过子集中的其他城市和边到达。两个子树被认为不一样的条件是至少有一个城市在其中一棵子树中存在,但在另一棵子树中不存在。
对于 d 从 1 到 n-1 ,请你找到城市间 最大距离 恰好为 d 的所有子树数目。
请你返回一个大小为 n-1 的数组,其中第 d 个元素(下标从 1 开始)是城市间 最大距离 恰好等于 d 的子树数目。
请注意,两个城市间距离定义为它们之间需要经过的边的数目。
输入:n = 4, edges = [[1,2],[2,3],[2,4]]
输出:[3,4,0]
解释:
子树 {1,2}, {2,3} 和 {2,4} 最大距离都是 1 。
子树 {1,2,3}, {1,2,4}, {2,3,4} 和 {1,2,3,4} 最大距离都为 2 。
不存在城市间最大距离为 3 的子树。
const int N = 20, M = 2 * N;
class Solution {
public:
int e[M], ne[M], h[N], idx;
vector<int> ans;
int x, dis;
bool st[N];
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
int dfs(int u, int state, int d){
int cnt = 1;
st[u] = true;
if(d > dis){
dis = d;
x = u;
}
for(int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
if((state >> j & 1) == 0 || st[j]) continue;
cnt += dfs(j, state, d + 1);
}
return cnt;
}
void dfs1(int u, int state, int d)
{
st[u] = true;
dis = max(dis, d);
for(int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
if(st[j] || (state >> j & 1) == 0) continue;
dfs1(j, state, d + 1);
}
}
vector<int> countSubgraphsForEachDiameter(int n, vector<vector<int>>& edges) {
memset(h, -1, sizeof h);
ans.resize(n - 1);
idx = 0;
for(auto &x : edges){
int a = x[0], b = x[1];
a --, b --;
add(a, b), add(b, a);
}
for(int i = 0; i < 1 << n; i ++)
{
if((i & (i - 1)) == 0) continue;
int start = 0, cnt = 0;
for(int k = 0; k < n; k ++){
if(i >> k & 1){
start = k;
cnt ++;
}
}
memset(st, 0, sizeof st);
dis = 0;
int c = dfs(start, i, 0);
if(cnt == c){
dis = 0;
memset(st, 0, sizeof st);
dfs1(x, i, 0);
ans[dis - 1] += 1;
}
}
return ans;
}
};