wiki 方格取数2 网络流 最大流最小费用流

来源:互联网 发布:怎么把微店搬到淘宝 编辑:程序博客网 时间:2024/06/01 09:32

建模过程:

每个方格拆成两个点,入点s和出点e。从s到e加一条cost为该方格对应的数,容量为1边。另外s到e再加一条cost为0,容量为无穷的边。如果方格i可以通向方格j,则从方格i的出点想方格j的入点加一条cost为0,容量为无穷的边。最后建立一个超级源点,向(0,0)这个方格的入点建一条容量为K,cost为0的边。之后求最大流最小费用流。因为此题求最大值,因此所有的cost都取相反数。

AC代码:

#include <iostream>#include <stdio.h>#include <string.h>#include <queue>#include <vector>using namespace std;#define INT_MAX 0x07777777struct Edge {    int from, to, cap, flow, cost;};int n,k,terminal,result;int map[60][60],a[5100],p[5100],v[5100],t[5100];vector<Edge> edges;vector<int> G[5100];void addEdge(int from, int to, int cap, int flow, int cost){    edges.push_back(Edge{from,to,cap,0,cost});    edges.push_back(Edge{to,from,0,0,-cost});    int temp = edges.size();    G[from].push_back(temp-2);    G[to].push_back(temp-1);}void init(){    scanf("%d %d", &n, &k);    for(int i = 0; i < n; i++){        for(int j = 0; j < n; j++){            scanf("%d", &map[i][j]);        }    }    addEdge(0,1,k,0,0);    for(int i = 0; i < n; i++){        for(int j = 0; j < n; j++){            int temp = i*n+j;            addEdge(temp*2+1, temp*2+2, 1, 0, -map[i][j]);            addEdge(temp*2+1, temp*2+2, INT_MAX, 0, 0);            if(i < n-1){                addEdge(temp*2+2,temp*2+2+(n-1)*2+1,INT_MAX,0,0);            }            if(j < n-1){                addEdge(temp*2+2,temp*2+3,INT_MAX,0,0);            }        }    }    terminal = n*n*2;    result = 0;}void solve (){    while(true){        memset(v, 0, sizeof(v));        memset(p, -1, sizeof(p));        memset(a, 0,sizeof(a));        for(int i = 0; i < 5100; i++) {            t[i] = INT_MAX;        }        queue<int> q;        q.push(0);        a[0] = INT_MAX;        t[0] = 0;        while(!q.empty()){            int u = q.front();            v[u] = 0;            q.pop();            for(int i = 0; i < G[u].size(); i++){                Edge& e = edges[G[u][i]];                if(e.cap > e.flow && t[e.to] > t[e.from]+e.cost){                    t[e.to] = t[e.from]+e.cost;                    a[e.to] = (a[e.from] > e.cap-e.flow ? e.cap-e.flow : a[e.from]);                    p[e.to] = G[u][i];                    if(!v[e.to]) {q.push(e.to); v[e.to] = 1;}                                    }            }        }        if(a[terminal]==0) break;        result += a[terminal]*t[terminal];        int u = terminal;        while(u){            edges[p[u]].flow += a[terminal];            edges[p[u]^1].flow -= a[terminal];            u = edges[p[u]].from;        }    }}int main(int argc, const char * argv[]){    init();    solve();    printf("%d\n", -result);}


0 0
原创粉丝点击