• HDU 4085 斯坦纳树+DP


    https://cn.vjudge.net/problem/HDU-4085

    给你n,m,k ,分别表示有n个点,m条边,每条边有一个权值,表示修复这条边需要的代价

    从前k个点中任取一个使其和后k个点中的某一个点,通过边连接,并且必须是一一对应,问最小的代价是多少。

    先用斯坦纳树模板求出f[i][1<<k]    然后用dp[i]表示所有点为根的情况下连通状态为i的最小花费

    这样我们就可以从1dp到1<<k得到答案 注意dp之前要先判总状态是否合法 再判子集是否合法 最后再进行dp更新

    #include<bits/stdc++.h>
    #define N 6003
    #define inf 1000000000
    using namespace std;
    int n, m, k, tot;
    int point[N], next1[N], v[N], len[N];
    int f[53][(1 << 11)], mi[20], can[N], dp[(1 << 11)];
    queue<int> p;
    void add(int x, int y, int z) {
            tot++;
            next1[tot] = point[x];
            point[x] = tot;
            v[tot] = y;
            len[tot] = z;
            tot++;
            next1[tot] = point[y];
            point[y] = tot;
            v[tot] = x;
            len[tot] = z;
    }
    void spfa(int sta) {
            while (!p.empty()) {
                    int now = p.front();
                    p.pop();
                    for (int i = point[now]; i; i = next1[i]) {
                            if (f[v[i]][sta] > f[now][sta] + len[i]) {
                                    f[v[i]][sta] = f[now][sta] + len[i];
                                    if (!can[v[i]]) {
                                            can[v[i]] = 1;
                                            p.push(v[i]);
                                    }
                            }
                    }
                    can[now] = 0;
            }
    }
    bool check(int sta) { //判断当前的状态是否满足一一对应关系
            int ans = 0;
            for (int i = 0; i < k; i++) {
                    if (sta & (1 << i))
                            ans++;
                    if (sta & (1 << (i + k)))
                            ans--;
            }
            return (ans == 0);
    }
    int main() {
            int t;
            scanf("%d", &t);
            mi[0] = 1;
            for (int i = 1; i <= 11; i++)
                    mi[i] = mi[i - 1] * 2;
            for (int T = 1; T <= t; T++) {
                    scanf("%d%d%d", &n, &m, &k);
                    tot = 0;
                    memset(point, 0, sizeof(point));
                    memset(next1, 0, sizeof(next1));
                    for (int i = 1; i <= m; i++) {
                            int x, y, z;
                            scanf("%d%d%d", &x, &y, &z);
                            add(x, y, z);
                    }
                    for (int i = 1; i <= n; i++)
                            for (int j = 0; j < mi[10]; j++)
                                    f[i][j] = inf;
                    for (int i = 1; i <= k; i++)
                            f[i][mi[i - 1]] = 0;
                    int t = k;
                    for (int i = n - k + 1; i <= n; i++)
                            f[i][mi[t]] = 0, t++;
                    for (int sta = 1; sta < mi[t]; sta++) {
                            for (int i = 1; i <= n; i++) {
                                    for (int s = sta & (sta - 1); s; s = sta & (s - 1)) {
                                            int t = f[i][sta - s] + f[i][s];
                                            f[i][sta] = min(f[i][sta], t);
                                    }
                                    if (f[i][sta] != inf)
                                            p.push(i), can[i] = 1;
                            }
                            spfa(sta);
                    }
                    for (int sta = 1; sta < mi[t]; sta++) {
                            dp[sta] = inf;
                            for (int i = 1; i <= n; i++)
                            dp[sta] = min(dp[sta], f[i][sta]);
                    }
                    for (int sta = 1; sta < mi[t]; sta++)
                            if (check(sta))
                                    for (int s = sta & (sta - 1); s; s = sta & (s - 1))
                                            if (check(s))
                                                    dp[sta] = min(dp[sta], dp[s] + dp[sta - s]);
                    if (dp[mi[t] - 1] == inf)
                            printf("No solution
    ");
                    else
                            printf("%d
    ", dp[mi[t] - 1]);
            }
    }
    View Code
  • 相关阅读:
    斐波那契数列
    MySQL
    GIT
    shell执行Python并传参
    摘选改善Python程序的91个建议2
    摘选改善Python程序的91个建议
    django执行原生sql
    admin
    分支&循环
    git
  • 原文地址:https://www.cnblogs.com/Aragaki/p/10989578.html
Copyright © 2020-2023  润新知