zoukankan      html  css  js  c++  java
  • poj Kaka's Matrix Travels

                              Kaka's Matrix Travels

     

    题目:

       给出一个矩阵。求仅仅能向下或者向右的情况下能得到的最大和。一般的是指遍历一次,而这个是能够反复走K次。每经过一次后就把该点设为0.求最大和。

     

    算法:

       想到了用网络流做。可是建图没什么自信。看了别人的才敢開始建。建图事实上也不难,就是有一个拆点处理,由于,一个点走一次后其上的值就为0了。这个处理非常巧妙!就是拆点后建立两条边,一条是有价值的边,一条是没价值,可是能够通过的边。

    由于,尽管该点没价值,可是有可能其它点要通过它,这就是这题的巧妙之处。!!思抠以。。。

    。。

       给出一个分析的非常好的别人画的建图模型。

     

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int INF = 1 << 25;
    const int MAXN = 5000 + 10;
    
    //////////////////////////////
    //费用流
    
    struct Edge{
        int from,to,cap,flow,cost;
        Edge(){};
        Edge(int _from,int _to,int _cap,int _flow,int _cost)
            :from(_from),to(_to),cap(_cap),flow(_flow),cost(_cost){};
    };
    
    vector<Edge> edges;
    vector<int> G[MAXN];
    bool inq[MAXN];
    int d[MAXN];
    int p[MAXN];
    int a[MAXN];
    int N,K,V,src,sink;
    
    /////////////////////////////
    
    int matrix[MAXN][MAXN];
    void init(){
        src = N * N * 2; sink = src + 1;
        for(int i = 0; i < sink + 1;++i)
            G[i].clear();
        edges.clear();
    }
    
    void addEdge(int from,int to,int cap,int cost){
        edges.push_back(Edge(from,to,cap,0,cost));
        edges.push_back(Edge(to,from,0,0,-cost));
        int sz = edges.size();
        G[from].push_back(sz - 2);
        G[to].push_back(sz - 1);
    }
    
    bool spfa(int s,int t,int& flow,int& cost){
        for(int i = 0;i <= sink;++i) d[i] = INF;
        fill(inq,inq + V,false);
        d[s] = 0; inq[s] = true; p[s] = 0; a[s] = INF;
    
        queue<int> Q;
        Q.push(s);
        while(!Q.empty()){
            int u = Q.front(); Q.pop();
            inq[u] = false;
            for(int i = 0;i < (int)G[u].size();++i){
                Edge& e = edges[G[u][i]];
                if(e.cap > e.flow && d[e.to] > d[u] + e.cost){
                    d[e.to] = d[u] + e.cost;
                    p[e.to] = G[u][i];
                    a[e.to] = min(a[u],e.cap - e.flow);
                    if(!inq[e.to]){
                        inq[e.to] = true;
                        Q.push(e.to);
                    }
                }
            }
        }
    
        if(d[t] == INF)
            return false;
    
        flow += a[t];
        cost += d[t] * a[t];
        int u = t;
        while(u != s){
            edges[p[u]].flow += a[t];
            edges[p[u]^1].flow -= a[t];
            u = edges[p[u]].from;
        }
        return true;
    }
    
    int minCost(){
        V = sink + 1;
        int flow = 0,cost = 0;
        while(spfa(src,sink,flow,cost));
        return cost;
    }
    
    int main()
    {
    //    freopen("Input.txt","r",stdin);
    
        while(~scanf("%d%d",&N,&K)){
            init();
            for(int i = 0;i < N;++i){
                for(int j = 0;j < N;++j){
                    scanf("%d",&matrix[i][j]);
                }
            }
            V = N*N;
            int t;
            for(int i = 0;i < N;++i){          //拆点
                for(int j = 0;j < N;++j){
                    t = i * N + j;
                    addEdge(t,t + V,1,-matrix[i][j]);  //要这点的价值
                    addEdge(t,t + V,INF,0);          //其它点能够从这点过
                }
            }
            int t1,t2;
            for(int i = 0;i < N - 1;++i){   //向下建边
                for(int j = 0;j < N;++j){
                   t1 = i * N + j;
                   t2 = (i + 1) * N + j;
                   addEdge(t1 + V,t2,INF,0);
                }
            }
    
            for(int i = 0;i < N;++i){      //向右建边
                for(int j = 0;j < N - 1;++j){
                    t1 = i * N + j;
                    t2 = i * N + j + 1;
                    addEdge(t1 + V,t2,INF,0);
                }
            }
    
            addEdge(src,0,K,0);      //超级源点
            addEdge(2*V - 1,sink,K,0);  //超级汇点
    
            printf("%d
    ",-minCost());
        }
        return 0;
    }
    
    
    
    
    
    
    
    


     

  • 相关阅读:
    URAL 1998 The old Padawan 二分
    URAL 1997 Those are not the droids you're looking for 二分图最大匹配
    URAL 1995 Illegal spices 贪心构造
    URAL 1993 This cheeseburger you don't need 模拟题
    URAL 1992 CVS
    URAL 1991 The battle near the swamp 水题
    Codeforces Beta Round #92 (Div. 1 Only) A. Prime Permutation 暴力
    Codeforces Beta Round #7 D. Palindrome Degree hash
    Codeforces Beta Round #7 C. Line Exgcd
    Codeforces Beta Round #7 B. Memory Manager 模拟题
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/5093092.html
Copyright © 2011-2022 走看看