• BZOJ 2127 Happiness


    BZOJ 2127 Happiness

    (默认题面是 wyy PPT里面的题面)

    我们先考虑两个人的情况,如果只有两个人,考虑从 $ s $ 向它们连边,割掉表示帮,再从它们向 $ t $ 连边,表示不帮。同时如果两个人没有选择相同的行为,我们认为这样会产生损失,注意到如果两个人选择的行为不一样,如果我们把这两个人之间连一条双向边,仍然没有割掉。现在我们需要的就是确定这条双向边的权值。

    我们考虑建立出来的图是这样的:

    CBDA5CE0-BE18-45C8-B919-58AF91F8818C.png

    现在我们需要确定 $ a,b,c,d,e $ 的权值。

    我们用 $ v_1 $ 表示 同时选择帮忙的额外收益, $ v_2 $ 表示同时不帮的额外收益,那么:

    [c+d=v_2\a+b=v_1\a+d+e=v_1+v_2\b+c+e=v_1+v_2\ ]

    最后得到

    [e = frac{v_1+v_2}{2} , a=b=frac{v_1}{2} , c=d=frac {v_2}{2} ]

    所以我们可以这样建图:

    对于每个人建立一个点,从 $ s $ 向它连一条边,容量为它选择帮忙的收益加上它与周围所有人一起选择帮忙的收益的一半,再向 $ t $ 连边k,容量为不帮的收益 + 它与它周围所有人一起不帮的收益的一半。

    对于相邻的人,我们建立一条双向边权是同时选择帮忙或者不帮忙的平均数。

    这个图上跑最小割就可以了。

    #include "iostream"
    #include "algorithm"
    #include "cstring"
    #include "cstdio"
    #include "queue"
    #include "cmath"
    #include "vector"
    using namespace std;
    #define mem(a) memset( a , 0 , sizeof a )
    #define MAXN 6006
    #define inf 0x3f3f3f3f
    
    typedef long long ll;
    class maxFlow {
    private:
        int add(int u, int v, ll w) {
            nxt.push_back(head[u]);
            int x = ( head[u] = to.size() );
            to.push_back(v);
            cap.push_back(w);
            return x;
        }
    public:
        std::queue<int> q;
        std::vector<int> head, cur, nxt, to, dep;
        std::vector<ll> cap;
    
        maxFlow(int _n = 0) { init(_n); }
        void init(int _n) {
            head.clear();
            head.resize(_n + 1, 0);
            nxt.resize(2);
            to.resize(2);
            cap.resize(2);
        }
        void init() { init(head.size() - 1); }
        int Add(int u, int v, ll w) {
    //      printf("%d %d %d
    ",u,v,w);
            add(u, v, w);
            return add(v, u, 0);
        }
        void del(int x) { cap[x << 1] = cap[x << 1 | 1] = 0; }
        bool bfs(int s, int t, int delta) {
            dep.clear();
            dep.resize(head.size(), -1);
            dep[s] = 0;
            q.push(s);
            while (!q.empty()) {
                int u = q.front();
                q.pop();
                for (int i = head[u]; i; i = nxt[i]) {
                    int v = to[i];
                    ll w = cap[i];
                    if (w >= delta && dep[v] == -1) {
                        dep[v] = dep[u] + 1;
                        q.push(v);
                    }
                }
            }
            return ~dep[t];
        }
        ll dfs(int u, ll flow, int t, int delta) {
            if (dep[u] == dep[t])
                return u == t ? flow : 0;
            ll out = 0;
            for (int& i = cur[u]; i; i = nxt[i]) {
                int v = to[i];
                ll w = cap[i];
                if (w >= delta && dep[v] == dep[u] + 1) {
                    ll f = dfs(v, std::min(w, flow - out), t, delta);
                    cap[i] -= f;
                    cap[i ^ 1] += f;
                    out += f;
                    if (out == flow)
                        return out;
                }
            }
            return out;
        }
        ll maxflow(int s, int t) {
            ll out = 0;
            ll maxcap = *max_element(cap.begin(), cap.end());
            for (ll delta = 1ll << int(log2(maxcap) + 1e-12); delta; delta >>= 1) {
                while (bfs(s, t, delta)) {
                    cur = head;
                    out += dfs(s, 0x7fffffffffffffffll, t, delta);
                }
            }
            return out;
        }
        ll getflow(int x) const { return cap[x << 1 | 1]; }
    } F ;
    int n , m , k , s = 10001 , t = 10002;
    int id( int x , int y ) { return y ? ( x - 1 ) * m + y : s; }
    int main() {
        cin >> n >> m >> k;
        F.init( 10004 );
        for( int i = 1 ; i <= n ; ++ i ) {
            for( int j = 1 , w ; j <= m ; ++ j ) {
                scanf("%d",&w);
                F.Add( id( i , j - 1 ) , id( i , j ) , ~w ? 100 - w : inf );
            }
            F.Add( id( i , m ) , t , inf );
        }
        int a , b;
        while( k-- ) {
            scanf("%d%d",&a,&b);
            for( int i = 0 ; i < m ; ++ i ) {
                F.Add( id( a , i ) , id( b , i + 1 ) , inf );
            }
        }
        printf("%.2lf",100 - 1.0 * F.maxflow( s , t ) / n);
    }
    
  • 相关阅读:
    Search a 2D Matrix leetcode java
    Sqrt(int x) leetcode java
    Search for a Range leetcode java
    php获取客户端公网ip代码
    ddns+ros(routeros)+centos7.6+nginx+php+dnspod
    limits.conf文件修改注意事项,限制文件描述符数和进程数
    阿里云本地存储网关的一些特点和注意事项
    ROS根据访问不同的网址,走不同的路由策略的脚本
    漫威所有电影的 按时间线的观影顺序
    sklearn—特征工程
  • 原文地址:https://www.cnblogs.com/yijan/p/12335235.html
Copyright © 2020-2023  润新知