zoukankan      html  css  js  c++  java
  • AT2657 [ARC078D] Mole and Abandoned Mine

    简要题解如下:

    (1)(n) 的路径为关键路径。

    1. 注意到关键路径只有一条是解题的关键,可以思考这张图长什么样子。

    2. 不难发现关键路径上所有边均为桥,因此大致上是关键路径上每个点下面挂了很多个连通块。

    3. 基于这张图的形态涉及一个 (dp),令 (f_{i, S}) 表示当前只考虑 (S) 这个集合,当前在关键路径上走到的点为 (i) 留下的最大边权。

    4. 转移有两种,一种是直接考虑在关键路径上往后扩展一个点 (j),令一种方式是考虑在 (i) 下面挂上一个连通块 (T) 此处可以枚举子集。通过预处理等技巧可以做到 (mathcal{O(n ^ 2 2 ^ n + n 3 ^ n)})

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i, l, r) for (int i = l; i <= r; ++i)
    const int N = 20;
    const int M = (1 << 15) + 5;
    int n, m, u, v, c, L, all, g[M], w[N][N], f[N][M], dp[N][M];
    int main () {
        cin >> n >> m, L = (1 << n) - 1;
        memset(w, 128, sizeof(w)), memset(dp, 128, sizeof(dp));
        rep(i, 1, m) cin >> u >> v >> c, w[u][v] = w[v][u] = c, all += c;
        rep(S, 0, L) rep(i, 1, n) rep(j, 1, n) if((1 << (j - 1)) & S) f[i][S] += max(0, w[i][j]);
        rep(S, 0, L) {
            rep(i, 1, n) rep(j, 1, n) if(((1 << (i - 1)) & S) && ((1 << (j - 1)) & S)) g[S] += max(0, w[i][j]);
            g[S] /= 2;
        }
        dp[1][1] = 0;
        rep(S, 0, L) rep(i, 1, n) if(dp[i][S] >= 0) {
            rep(j, 1, n) 
                if(!((1 << (j - 1)) & S) && w[i][j] > 0) 
                    dp[j][S | (1 << (j - 1))] = max(dp[j][S | (1 << (j - 1))], dp[i][S] + w[i][j]);
            for (int T = (L ^ S); T; T = ((T - 1) & (L ^ S))) 
                dp[i][S | T] = max(dp[i][S | T], dp[i][S] + f[i][T] + g[T]);
        }
        printf("%d", all - dp[n][L]);
        return 0;
    }
    

    一定要将思路理清,考虑最终状态的时候一定要完全准确,否则可能会出现某些性质没有发现的情况。

  • 相关阅读:
    二维码生成代码
    部署javaweb项目到阿里云ecs(centos7)
    mysql基础知识
    IDEA快捷键快速补齐类和对象名
    Redis和elasticsearch
    在asp.net 项目的bin目录中使用子目录
    MVC项目引用备注
    OAuth相关备注
    手动安装windows的磁盘清理工具
    在CentOS上安装 MongoDB
  • 原文地址:https://www.cnblogs.com/Go7338395/p/14017005.html
Copyright © 2011-2022 走看看