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;
    }
    
    /*
    */
  • 相关阅读:
    Attach Files to Objects 将文件附加到对象
    Provide Several View Variants for End-Users 为最终用户提供多个视图变体
    Audit Object Changes 审核对象更改
    Toggle the WinForms Ribbon Interface 切换 WinForms 功能区界面
    Change Style of Navigation Items 更改导航项的样式
    Apply Grouping to List View Data 将分组应用于列表视图数据
    Choose the WinForms UI Type 选择 WinForms UI 类型
    Filter List Views 筛选器列表视图
    Make a List View Editable 使列表视图可编辑
    Add a Preview to a List View将预览添加到列表视图
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10760136.html
Copyright © 2011-2022 走看看