• 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;
        }
    };
    
  • 相关阅读:
    UVA 11806 组合数学+容斥
    Educational Codeforces Round 37 (Rated for Div. 2) G
    java 5 线程池
    团队-象棋游戏-项目进度
    结对-五子棋-测试过程
    结对-五子棋游戏-开发过程
    课后作业-阅读任务-阅读提问-2
    20171006-构建之法:现代软件工程-阅读笔记
    结队-五子棋游戏-项目进度
    团队-象棋游戏-代码设计规范
  • 原文地址:https://www.cnblogs.com/wdt1/p/13799666.html
Copyright © 2020-2023  润新知