a_lc_统计子树中城市之间最大距离(枚举子集 + floyd / 2*dfs 求直径)

返回一个大小为 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;
    }
};
posted @ 2020-10-11 22:00  童年の波鞋  阅读(97)  评论(0编辑  收藏  举报