返回一个大小为 n-1 的数组,其中第 d 个元素(下标从 1 开始)是城市间 最大距离 恰好等于 d 的子树数目。
2 <= n <= 15
思路
这题求解的方法会有很多,但共同点都是枚举子集:
- 检测子集的连通性+2*dfs求每个子集的直径
- floyd求每个点的最长距离
floyd求出n个点之间最短距离,枚举所有子集,对于每一个子集都去检查连通性,并求出两点之间的最长距离
const int N=20, inf=0x3f3f3f3f;
class Solution {
public:
int dp[N][N], sta[N][N];
vector<int> countSubgraphsForEachDiameter(int n, vector<vector<int>>& es) {
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
dp[i][j]=i==j ? 0:inf;
for (auto& e : es) {
int a=e[0]-1, b=e[1]-1;
sta[a][b]=sta[b][a]=1;
dp[a][b]=dp[b][a]=1;
}
for (int k=0; k<n; k++)
for (int i=0; i<n; i++)
for (int j=0; j<n; j++) if (i!=j && dp[i][k]!=inf && dp[k][j]!=inf) {
dp[i][j]=min(dp[i][j], dp[i][k]+dp[k][j]);
}
int tot=1<<n, maxD=1;
vector<int> ans(n-1, 0);
for (int st=1; st<tot; st++) {
vector<int> v;
for (int j=0; j<n; j++) if (st&(1<<j))
v.push_back(j);
if (v.size()<=1) continue;
int m=v.size(), edge=0, maxD=0;
for (int i=0; i<m-1; i++)
for (int j=i+1; j<m; j++) {
if (sta[v[i]][v[j]]) edge++;
maxD=max(maxD, dp[v[i]][v[j]]);
}
if (edge==m-1) ans[maxD-1]++;
}
return ans;
}
};