zoukankan      html  css  js  c++  java
  • [BZOJ 2127] Happiness

    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=2127

    [算法]

             首先默认每个人都选文科 

             那么 , "选"就是指选理科 , 而"不选"就是指选文科

             那么选所获得的收益就是(V理 - V文)

             而额外获得的收益可以看作是 : 若两个点同时选 , 可以获得一些收益和若两个点中有一个不选 , 则会失去收益

             解最大权闭合子图 , 即可

            时间复杂度 : O(dinic(N,M))

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    #define N 110
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int inf = 2e9;
    
    struct edge
    {
            int to , w , nxt;
    } e[N * N * 50];
    
    int total , tot , S , T , n , m;
    int head[N * N * 5] , dep[N * N * 5] , a[N][N] , b[N][N] , point[N][N];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void addedge(int u , int v , int w)
    {
            ++tot;
            e[tot] = (edge){v , w , head[u]};
            head[u] = tot;
            ++tot;
            e[tot] = (edge){u , 0 , head[v]};
            head[v] = tot;
    }
    inline bool bfs()
    {
            queue< int > q;
            for (int i = 1; i <= total; i++) dep[i] = -1;
            dep[T] = -1;
            q.push(S);
            dep[S] = 1;
            while (!q.empty())
            {
                    int cur = q.front();
                    q.pop();
                    for (int i = head[cur]; i; i = e[i].nxt)
                    {
                            int v = e[i].to , w = e[i].w;
                            if (w > 0 && dep[v] == -1)
                            {
                                    dep[v] = dep[cur] + 1;
                                    q.push(v);
                                    if (v == T) return true;
                            }
                    }
            }
            return false;
    }
    inline int dinic(int u , int flow)
    {
            int rest = flow;
            if (u == T)
                    return flow;
            for (int i = head[u]; i && rest; i = e[i].nxt)
            {
                    int v = e[i].to , w = e[i].w;
                    if (w > 0 && dep[v] == dep[u] + 1)
                    {
                            int k = dinic(v , min(rest , w));
                            if (!k) dep[v] = 0;
                            rest -= k;
                            e[i].w -= k;
                            e[i ^ 1].w += k;
                    }
            }
            return flow - rest;
    }
    
    int main()
    {
            
            read(n); read(m);
            int ans = 0;
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j <= m; j++)
                    {
                            read(a[i][j]);        
                    }        
            }
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j <= m; j++)
                    {
                            read(b[i][j]);
                            ans += b[i][j];
                    }
            }
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j <= m; j++)
                    {
                            point[i][j] = ++total;                
                    }
            }
            tot = 1;
            S = 0 , T = 5 * N * N - 1;
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j <= m; j++)
                    {
                            if (a[i][j] >= b[i][j]) 
                            {
                                    ans += a[i][j] - b[i][j];
                                    addedge(S , point[i][j] , a[i][j] - b[i][j]);
                            } else addedge(point[i][j] , T  , b[i][j] - a[i][j]);        
                    }        
            }
            // NM + 4NM = 5NM
            // 24NM + 2NM = 26NM
            for (int i = 1; i < n; i++)
            {
                    for (int j = 1; j <= m; j++)
                    {
                            int x;
                            read(x);
                            ans += x;
                            ++total;
                            addedge(S , total , x);
                            addedge(total , point[i][j] , inf);
                            addedge(total , point[i + 1][j] , inf);
                    }
            }
            for (int i = 1; i < n; i++)
            {
                    for (int j = 1; j <= m; j++)
                    {
                            int x;
                            read(x);
                            ans += x;
                            ++total;
                            addedge(total , T , x);
                            addedge(point[i][j] , total , inf);
                            addedge(point[i + 1][j] , total , inf);
                    }
            }
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j < m; j++)
                    {
                            int x;
                            read(x);
                            ans += x;
                            ++total;
                            addedge(S , total , x);
                            addedge(total , point[i][j] , inf);
                            addedge(total , point[i][j + 1] , inf);
                    }
            }
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j < m; j++)
                    {
                            int x;
                            read(x);
                            ans += x;
                            ++total;
                            addedge(total , T , x);
                            addedge(point[i][j] , total , inf);
                            addedge(point[i][j + 1] , total , inf);
                    }
            }
            while (bfs())
            {
                    while (int flow = dinic(S , inf)) ans -= flow;
            }
            printf("%d
    " , ans);
            
            return 0;
        
    }

             

  • 相关阅读:
    JSP内置对象
    java 中list还有array的区别
    js动态修改界面碰见的疑惑
    购物多条件商品查询逻辑处理
    数据库信息备份
    关于毕设的一些小问题
    在<a></a>标签中正确调用javaScript脚本
    oracle实训0705经验
    第十五天学习进度--数列找规律算法(预测算法)(1)
    第十四天学习进度--相关系数和显著水平
  • 原文地址:https://www.cnblogs.com/evenbao/p/10360288.html
Copyright © 2011-2022 走看看