• 【图论】最小路径覆盖


    狄尔沃斯定理:最小路径覆盖=最长反链

    最小不相交路径覆盖:使用最小条数的路径,覆盖每个点恰好1次。
    最小可相交路径覆盖:使用最小条数的路径,每个点可以覆盖多次。

    最小可相交路径覆盖做一次Floyd传递闭包变成最小不相交路径覆盖。
    最小不相交路径覆盖使用二分图匹配:把每个点x拆成x1(出度)和x2(入度),初始状态没有匹配,使用的路径数量是n(单个点也是一个路径),然后原图加的边会匹配一个出度和一个入度,然后向超级源点和超级汇点分别连权值为1的边,那么每个点的出度和入度必然是0或者1,这样求出最大流之后,用n减去最大流就是最小路径覆盖。

    树的最小路径覆盖

    使用树形dp解决,设 (dp[u][d]) 表示u节点的子树中,u节点参与的路径覆盖度数至多为d时的结果。

    那么显然有

    (dp[u][0]=min(dp[u][0],1+sum_{vin ch[u]} dp[v][2])) 表示这个点,不参加子树的路径,自己作为路径的结尾
    (dp[u][1]=min(dp[u][1],dp[v_1][1]+sum_{vin ch[u],v eq v_1} dp[v][2]) 表示这个点加入子树v1的路径,前提是子树v1有空间接收它。
    $dp[u][2]=min(dp[u][2],dp[v_1][1]+dp[v_2][1]-1+sum_{vin ch[u],v eq v_1,v eq v_2} dp[v][2] $ 表示这个点加入子树v1v2的路径,前提是子树v1v2有空间接收它。

    问题的边界是叶子。
    (dp[u][0]=1)
    (dp[u][1]=1)
    (dp[u][2]=1)

        int dp[200005][3];
    
        void dfs(int u, int p) {
            int sum = 0;
            vector<int> vec;
            for(int v : G[u]) {
                if(v == p)
                    continue;
                dfs(v, u);
                sum += dp[v][2];
                vec.eb(dp[v][1] - dp[v][2]);
            }
            sort(all(vec));
            dp[u][0] = sum + 1;
            dp[u][1] = (vec.size() >= 1) ? (sum + vec[0]) : INF;
            dp[u][2] = (vec.size() >= 2) ? (sum + vec[0] + vec[1] - 1) : INF;
    
            dp[u][1] = min(dp[u][1], dp[u][0]);
            dp[u][2] = min(dp[u][2], dp[u][1]);
            return;
        }
    

    CF618D - Hamiltonian Spanning Tree

  • 相关阅读:
    每日日报
    每日日报
    flink入门到实战(2)flink优化总结
    flink入门到实战(1)入门学习
    机器学习算法一般步骤
    hadoop入门到实战(1)hive优化总结
    划重点|iOS15正式发布, 全新的通知推送系统,你必须要知道!
    云知声 Atlas 超算平台: 基于 Fluid + Alluxio 的计算加速实践
    终端卡顿优化的全记录
    云湖共生释放企业数据价值
  • 原文地址:https://www.cnblogs.com/purinliang/p/14225530.html
Copyright © 2020-2023  润新知