zoukankan      html  css  js  c++  java
  • Codeforces 1155F Delivery Oligopoly dp(看题解)

    看别人写的才学会的。。。

    我们考虑刚开始的一个点, 然后我们枚举接上去的一条一条链,

    dp[mask]表示当前已经加进去点的状态是mask所需的最少边数。

    反正就是很麻烦的一道题, 让我自己写我是写不出来的。。。 我好菜啊。

    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    
    using namespace std;
    
    const int N = 1e6 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e6 + 3;
    const int p = 1e6 + 3;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}
    
    int n, m;
    int G[14][14];
    int vtomask[14][1 << 14];
    int dp[1 << 14], pre[1 << 14][3];
    vector<int> road[1 << 14][14][14];
    vector<PII> ans;
    
    int main() {
        memset(dp, inf, sizeof(dp));
        scanf("%d%d", &n, &m);
        for(int i = 0; i < m; i++) {
            int u, v; scanf("%d%d", &u, &v);
            u--; v--;
            G[u][v] = G[v][u] = 1;
        }
        for(int i = 0; i < n; i++) {
            for(int mask = 0; mask < (1 << n); mask++) {
                for(int j = 0; j < n; j++) {
                    if(mask >> j & 1) {
                        if(G[i][j]) vtomask[i][mask]++;
                    }
                }
            }
        }
        for(int i = 0; i < n; i++) road[1 << i][i][i].push_back(i);
        for(int mask = 0; mask < (1 << n); mask++) {
            for(int u = 0; u < n; u++) {
                for(int v = 0; v < n; v++) {
                    if(!SZ(road[mask][u][v])) continue;
                    for(int z = 0; z < n; z++) {
                        if(mask >> z & 1) continue;
                        if(!G[v][z]) continue;
                        int nxtmask = mask | (1 << z);
                        if(SZ(road[nxtmask][u][z])) continue;
                        road[nxtmask][u][z] = road[mask][u][v];
                        road[nxtmask][u][z].push_back(z);
                    }
                }
            }
        }
        dp[1] = 0;
        for(int mask = 1; mask < (1 << n); mask++) {
            if(dp[mask] >= inf) continue;
            for(int u = 0; u < n; u++) {
                if(mask >> u & 1) continue;
                if(!vtomask[u][mask]) continue;
                if(vtomask[u][mask] >= 2) {
                    int nxtmask = mask | (1 << u);
                    if(chkmin(dp[nxtmask], dp[mask] + 2)) {
                        pre[nxtmask][0] = mask;
                        pre[nxtmask][1] = u;
                        pre[nxtmask][2] = -1;
                    }
                }
                for(int v = u + 1; v < n; v++) {
                    if(mask >> v & 1) continue;
                    if(!vtomask[v][mask]) continue;
                    int amask = ((1 << n) - 1) ^ mask ^ (1 << u) ^ (1 << v);
                    for(int smask = amask; ; smask = (smask - 1) & amask) {
                        int tmask = smask | (1 << u) | (1 << v);
                        if(SZ(road[tmask][u][v])) {
                            if(chkmin(dp[mask | tmask], dp[mask] + SZ(road[tmask][u][v]) + 1)) {
                                pre[mask | tmask][0] = mask;
                                pre[mask | tmask][1] = u;
                                pre[mask | tmask][2] = v;
                            }
                        }
                        if(!smask) break;
                    }
                }
            }
        }
        printf("%d
    ", dp[(1 << n) - 1]);
        int mask = (1 << n) - 1;
        while(mask != 1) {
            int pmask = pre[mask][0];
            int u = pre[mask][1];
            int v = pre[mask][2];
            if(~v) {
                int tmask = mask ^ pmask;
                for(int i = 1; i < SZ(road[tmask][u][v]); i++)
                    ans.push_back(mk(road[tmask][u][v][i - 1], road[tmask][u][v][i]));
                for(int i = 0; i < n; i++) {
                    if((pmask >> i & 1) && G[u][i]) {
                        ans.push_back(mk(i, u));
                        break;
                    }
                }
                for(int i = 0; i < n; i++) {
                    if((pmask >> i & 1) && G[v][i]) {
                        ans.push_back(mk(i, v));
                        break;
                    }
                }
            } else {
                for(int i = 0, c = 2; c; i++) {
                    if(G[u][i] && (pmask >> i & 1)) {
                        ans.push_back(mk(u, i));
                        c--;
                    }
                }
            }
            mask = pmask;
        }
        for(auto& t : ans) printf("%d %d
    ", t.fi + 1, t.se + 1);
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    poj 2485 Highways 最小生成树
    hdu 3415 Max Sum of MaxKsubsequence
    poj 3026 Borg Maze
    poj 2823 Sliding Window 单调队列
    poj 1258 AgriNet
    hdu 1045 Fire Net (二分图匹配)
    poj 1789 Truck History MST(最小生成树)
    fafu 1181 割点
    减肥瘦身健康秘方
    人生的问题
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10760136.html
Copyright © 2011-2022 走看看