zoukankan      html  css  js  c++  java
  • MUTC 1 D Matrix 线性代数 网络流

    Matrix

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 825    Accepted Submission(s): 212


    Problem Description
    Let A be a 1*N matrix, and each element of A is either 0 or 1. You are to find such A that maximize D=(A*B-C)*AT, where B is a given N*N matrix whose elements are non-negative, C is a given 1*N matrix whose elements are also non-negative, and AT is the transposition of A (i.e. a N*1 matrix).
     

    Input
    The first line contains the number of test cases T, followed by T test cases.
    For each case, the first line contains an integer N (1<=N<=1000).
    The next N lines, each of which contains N integers, illustrating the matrix B. The jth integer on the ith line is B[i][j].
    Then one line followed, containing N integers, describing the matrix C, the ith one for C[i].
    You may assume that sum{B[i][j]} < 2^31, and sum{C[i]} < 2^31.
     

    Output
    For each case, output the the maximum D you may get.
     

    Sample Input
    1 3 1 2 1 3 1 0 1 2 3 2 3 7
     

    Sample Output
    2
    Hint
    For sample, A=[1, 1, 0] or A=[1, 1, 1] would get the maximum D.
     

    Author
    BUPT
     

    Source
     

    Recommend
    zhuyuanchen520
     

    -----------------------

    转自苟大神的博客

    题目:Matrix

     

    之所以能够用最大流解决这个问题,关键在于最大流可以求解下面这个函数的最小值:

    接下来就分析一下如何用最大流求解上面这个函数的极值。

    首先xi一共只有两种选择,那么最终可以按xi的取值将xi划分成两个集合,那么如果xi在值为1的集合里,xj在值为0的集合里,那么就会

    产生一个代价cij。同时如果xi选择0就会产生一个bi的代价,如果xi选择1就会产生一个ai的代价。于是构造一个源点S,汇点T做最小

    割,不妨假设做完最小割之后值为1的xi的集合是和S相连的部分,值为0的xi的集合是和T相连的部分。

     

    由于表达式中有三项,我们用三种割边来分别描述这三项的值。一种是xi选择了1,这样就不能选择0,需要把xi-T这条边割掉,由于xi

    选择1会产生ai的代价,那么就把这条边的容量设为ai。另一种是xi选择了0,这样就不能选择1,需要把S-xi这条边割掉,由于xi选择0会

    产生bi的代价,那么就把这条边的容量设为bi。最后一种是xi选择了1,xj选择了0,这样xi和xj不能在同一个集合中,需要把xi-xj这条边割

    掉,由于xi选择1,xj选择0产生cij的代价,那么就把这条边的容量设为cij。这样对建好的图做最小割就可以得到上面哪个函数的最小

    值。

     

    接着我们分析这个题目如何转化成上面这种模型。首先我们将D的表达式赤裸裸地写出来:


    这种形式必然不能看出来和上面那个表达式有什么关系,于是我们继续将其化简:

    如果令f等于最后一行括号里的内容,那么发生了什么?如果ai选择0会产生sum{bij}(1<=j<=N)的代价,如果ai选择1会产生ci的代价,如

    果ai选择1且aj选择0就会产生bij的代价。这样就完全转化成了上面的模型。

    ----------------------

    白书上的模板效率果然非常低

    ----------------------

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    
    using namespace std;
    
    const int maxn=2222;
    const int maxm=2222222;
    const int INF=1e9;
    
    struct Edge{
        int from,to,cap,flow;
    };
    
    struct Dinic{
        int n,m,s,t;
        vector<Edge>edges;
        vector<int>G[maxn];
        bool vis[maxn];
        int d[maxn];
        int cur[maxn];
    
        void init(int n,int s,int t){
            this->n=n;
            this->s=s;
            this->t=t;
            for (int i=0;i<n;i++) G[i].clear();
            edges.clear();
            m=0;
        }
    
        void addedge(int from,int to,int cap){
            edges.push_back((Edge){from,to,cap,0});
            edges.push_back((Edge){to,from,0,0});
            m=edges.size();
            G[from].push_back(m-2);
            G[to].push_back(m-1);
        }
    
        bool BFS(){
            memset(vis,0,sizeof(vis));
            queue<int>que;
            que.push(s);
            d[s]=0;
            vis[s]=true;
            while (!que.empty()){
                int x=que.front();que.pop();
                for (int i=0;i<G[x].size();i++){
                    Edge& e=edges[G[x][i]];
                    if (!vis[e.to]&&e.cap>e.flow){
                        vis[e.to]=true;
                        d[e.to]=d[x]+1;
                        que.push(e.to);
                    }
                }
            }
            return vis[t];
        }
    
        int DFS(int x,int a){
            if (x==t||a==0) return a;
            int flow=0,f;
            for (int& i=cur[x];i<G[x].size();i++){
                Edge& e=edges[G[x][i]];
                if (d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
                    e.flow+=f;
                    edges[G[x][i]^1].flow-=f;
                    flow+=f;
                    a-=f;
                    if (a==0) break;
                }
            }
            return flow;
        }
    
        long long Maxflow(int s,int t){
            this->s=s;
            this->t=t;
            long long flow=0;
            while (BFS()){
                memset(cur,0,sizeof(cur));
                flow+=DFS(s,INF);
            }
            return flow;
        }
    
    }solver;
    
    int b[maxn][maxn];
    int c[maxn];
    
    int main()
    {
        int T,n,s,t,a,x;
        long long sum;
        scanf("%d",&T);
        while (T--)
        {
            scanf("%d",&n);
            s=0;
            t=n+1;
            solver.init(n+2,s,t);
            sum=0;
            for (int i=1;i<=n;i++)
            {
                a=0;
                for (int j=1;j<=n;j++)
                {
                    scanf("%d",&x);
                    a+=x;
                    solver.addedge(i,j,x);
                }
                sum+=a;
                solver.addedge(s,i,a);
            }
            for (int i=1;i<=n;i++)
            {
                scanf("%d",&x);
                solver.addedge(i,t,x);
            }
            printf("%I64d\n",sum-solver.Maxflow(s,t));
        }
        return 0;
    }
    





  • 相关阅读:
    LeetCode 258 Add Digits
    LeetCode 231 Power of Two
    LeetCode 28 Implement strStr()
    LeetCode 26 Remove Duplicates from Sorted Array
    LeetCode 21 Merge Two Sorted Lists
    LeetCode 20 Valid Parentheses
    图形处理函数库 ImageTTFBBox
    php一些函数
    func_get_arg(),func_get_args()和func_num_args()的用法
    人生不是故事,人生是世故,摸爬滚打才不会辜负功名尘土
  • 原文地址:https://www.cnblogs.com/cyendra/p/3226310.html
Copyright © 2011-2022 走看看