pku 3422 Kaka's Matrix Travels 最大费用最大流

http://poj.org/problem?id=3422

/*

题意:给定一个n*n的矩形方格,要求从(1,1)出发,只能往右下角走,(i + 1,j) 或者 (i + n,j)每次走完将格子里面的数累加,并将所走过的格子里面的数置零,问走k能得到的最大的数:

*/

/*

 网络流的题目建图是关键,这道题目建图很难想啊!首先要拆点。这里将一个点拆分成两个点,建立两条边,一条变得流量为1,权值为 map[i][j],另一条则是流量为无穷,权值为0了。注意这条边是为了保证在走过该店后,map[i][j]为0后,还能继续走因为它有流量且权值为0. 还有就是往右下角走建立流量为无穷权值为0的边。最后要建立的就是超级源点与汇点的边了,都是流量为k权值为0的边,保证走k次。

*/

code:

#include <cstdio>

#include <cstring>

#include <iostream>

#include <queue>

#define maxn 5005

using namespace std;



const int inf = 99999999;



struct node

{

    int u,v;

    int c,w;

    int next;

}g[maxn*100];

int head[maxn],cnt,pre[maxn];

int dis[maxn],map[maxn][maxn];

bool inq[maxn];

int n,m,k,s,t,ans;



//为静态表初始化

void init()

{

    memset(head,-1,sizeof(head));

    cnt = 0;

}

//加边,记住反向边去权值取反

void add(int u,int v,int c,int w)

{

    g[cnt].u = u; g[cnt].v = v; g[cnt].c = c; g[cnt].w = w;

    g[cnt].next = head[u]; head[u] = cnt++;



    g[cnt].u = v; g[cnt].v = u; g[cnt].c = 0; g[cnt].w = -w;

    g[cnt].next = head[v]; head[v] = cnt++;

}

void spfa()

{

    int i;

    queue<int>q;

    for (i = 0; i <= t; ++i)

    {

        dis[i] = -inf;

        inq[i] = false;

        pre[i] = -1;

    }

    q.push(s); inq[s] = true;

    dis[s] = 0;

    while (!q.empty())

    {

        int u = q.front(); q.pop();

        inq[u] = false;

        for (i = head[u]; i != -1; i = g[i].next)

        {

            int v = g[i].v;

            if (g[i].c && dis[v] < dis[u] + g[i].w)

            {

                dis[v] = dis[u] + g[i].w;

                pre[v] = i;//注意这里记录的是这一条边了

                if (!inq[v])

                {

                    inq[v] = true;

                    q.push(v);

                }

            }

        }

    }

}

void MCMF()

{

   while (1)

   {

       spfa();

       if (pre[t] == -1) break;

       int x = t,minf = inf;

       while (x != s)

       {

           minf = min(minf,g[pre[x]].c);

           x = g[pre[x]].u;

       }

       x = t;

       while (x != s)

       {

           g[pre[x]].c -= minf;

           g[pre[x]^1].c += minf;

           x = g[pre[x]].u;

       }

       ans += minf*dis[t];

   }

}

int main()

{

    int i,j;

    scanf("%d%d",&n,&k);

    int tmp = n*n;

    init();

    //关键是建边的过程

    for (i = 1; i <= n; ++i)

    {

        for (j = 1; j <= n; ++j)

        {

            scanf("%d",&map[i][j]);

            int x = (i - 1)*n + j;

            int y = x + tmp;

            add(x,y,1,map[i][j]);

            add(x,y,inf,0);

            if (i < n) add(y,x + n,inf,0);

            if (j < n) add(y,x + 1,inf,0);

        }

    }

    s = 0; t = 2*tmp + 1;

    add(s,1,k,0);

    add(2*tmp,t,k,0);

    ans = 0;

    MCMF();

    printf("%d\n",ans);

    return 0;

}

  

你可能感兴趣的:(Matrix)