POJ 3422 Kaka's Matrix Travels 【最小费用最大流】

题意:

卡卡有一个矩阵,从左上角走到右下角,卡卡每次只能向右或者向下。矩阵里边都是不超过1000的正整数,卡卡走过的元素会变成0,问卡卡可以走k次,问卡卡最多能积累多少和。

思路:

最小费用最大流的题目。

建图自己没想出来,看了大神的建边,把每个点分解成两个点,一个代表进入一个代表出去,然后每个进入和每个出去连边,容量是1价值是这个点的矩阵的数值。然后因为可以不进去,所以起点要和别的矩阵元素的起点建边,终点也要和别的矩阵矩阵元素的起点建边,最后跑下最小费用最大流。

这题最右下角的矩阵元素需要特殊处理下.然后源点和左上角的矩阵元素的起点连边,容量为k,权值是0.

#include<stdio.h>
#include<queue>
#define MAXN 6003
#define MAXM 10002*4
#define INF  10000000
using namespace std;
//起点编号必须最小,终点编号必须最大
bool vis[MAXN];                    //spfa中记录是否在队列里边
struct edge{
    edge *next,*op;                //op是指向反向边
    int t,c,v;                     //t下一个点编号,c容量,v权值
}ES[MAXM],*V[MAXN];                //ES边静态邻接表,V点的编号
int N,M,S,T,EC=-1;                 //S源点最小,T汇点最大,EC当前边数
int demond[MAXN],sp[MAXN],prev[MAXN]; //spSPFA中记录距离,prev记录上一个点路径
edge *path[MAXN];                  //与prev同步记录,记录到上一条边
void addedge(int a,int b,int v,int c=INF){
    edge e1={V[a],0,b,c,v},e2={V[b],0,a,0,-v};
    ES[++EC]=e1;V[a]=&ES[EC];
    ES[++EC]=e2;V[b]=&ES[EC];
    V[a]->op=V[b];V[b]->op=V[a];
}
void init(){
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            int tmp;
            scanf("%d",&tmp);
            addedge((i-1)*n+j,n*n+(i-1)*n+j,-tmp,1);
            if(j<n){
                addedge(n*n+(i-1)*n+j,(i-1)*n+j+1,0);
                addedge((i-1)*n+j,(i-1)*n+j+1,0);
            }
            if(i<n){
                addedge(n*n+(i-1)*n+j,i*n+j,0);
                addedge((i-1)*n+j,i*n+j,0);
            }
        }
    S=0,T=n*n*2+1;
    addedge(n*n,T,0);
    addedge(S,1,0,k);
    addedge(n*n*2,T,0);
}
bool SPFA(){
    int u,v;
    for(u=S;u<=T;u++){
        sp[u]=INF;
    }
    queue<int>q;
    prev[S]=-1;
    q.push(S);
    sp[S]=0;
    vis[S]=1;
    while(!q.empty()){
        u=q.front();
        vis[u]=0;
        q.pop();
        for(edge *k=V[u];k;k=k->next){
            v=k->t;
            if(k->c>0&&sp[u]+k->v<sp[v]){
                sp[v]=sp[u]+k->v;
                prev[v]=u;
                path[v]=k;
                if(vis[v]==0){
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    return sp[T]!=INF;
}
int argument(){
    int i,cost=INF,flow=0;
    edge *e;
    for(i=T;prev[i]!=-1;i=prev[i]){
        e=path[i];
        if(e->c<cost)cost=e->c;
    }
    for(int i=T;prev[i]!=-1;i=prev[i]){
        e=path[i];
        e->c-=cost;e->op->c+=cost;
        flow+=e->v*cost;
    }
    return flow;
}
int maxcostflow(){
    int Flow=0;
    while(SPFA()){
        Flow+=argument();
    }
    return Flow;
}
int main(){
    init();
    printf("%d\n",-maxcostflow());
    return 0;
}

POJ 3422 Kaka's Matrix Travels 【最小费用最大流】

时间: 2024-10-02 04:32:24

POJ 3422 Kaka's Matrix Travels 【最小费用最大流】的相关文章

POJ 3422 Kaka&#39;s Matrix Travels(费用流)

POJ 3422 Kaka's Matrix Travels 题目链接 题意:一个矩阵,从左上角往右下角走k趟,每次走过数字就变成0,并且获得这个数字,要求走完之后,所获得数字之和最大 思路:有点类似区间k覆盖的建图方法,把点拆了,每个点有值的只能选一次,其他都是无值的,利用费用流,入点出点之间连一条容量1,有费用的边,和一条容量k - 1,费用0的边,然后其他就每个点和右边和下边2个点连边,然后跑费用流 代码: #include <cstdio> #include <cstring&g

poj 3422 Kaka&#39;s Matrix Travels (费用流)

Kaka's Matrix Travels Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7743   Accepted: 3111 Description On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels with SUM = 0. For each travel, Kaka mo

POj3422 Kaka&#39;s Matrix Travels 最小费用最大流 拆点

题目链接: poj3422 题意: 有一个N X N的矩阵, 矩阵的每一小格都有且仅有一个数字v,kaka每经过一个数字就会把它捡起来并将那个数字加到sum上去. 现在kaka能通过向下或向右走的方式从 (1,1)到(n,n)  K次,问kaka能取到的最大的sum是多少. 解题思路: 题目问题可以抽象为   求多次可走重复路的最长路的最大和问题 首先想到的就应该是最小费用最大流, 而题目要求的最大和值,那么应求就是最大费用最大流, 仅仅只需要将代码中的最小路算法改为最长路算法即可 题目的条件是

poj 3422 Kaka&#39;s Matrix Travels 最小费最大流

输入的时候没有取反,一直ole. 这里也是用到拆点,将一个点拆成p和q,这两个之间连接两条路,一条cap=1和cost=矩阵上的值,另一条为cap=k和cost=0.在将0和2*n *n+1看成源点和汇点. #include<stdio.h> #include<string.h> #include<vector> #include<queue> #include<algorithm> using namespace std; const int

POJ 3422 Kaka&#39;s Matrix Travels (最小费用最大流)

POJ 3422 Kaka's Matrix Travels 链接:http://poj.org/problem?id=3422 题意:有一个N*N的方格,每个方格里面有一个数字.现在卡卡要从左上角走到右下角,规定每次只能向下或者向右走,每次走到一个格子,将得到该格子的数字,并且该格子的数字变为0.当卡卡走一次时,很容易求出最大值,问卡卡走k次,能够得到的最大值为多少. 思路:最小费用最大流 关键是如何构图 1. 将N*N个格点拆分为两个点(i,i + N*N),每个点之间连一条流量为1,费用为

POJ 3422 Kaka&#39;s Matrix Travels(最大费用最大流 + 拆点)

题目链接:http://poj.org/problem?id=3422 Description On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels with SUM = 0. For each travel, Kaka moves one rook from the left-upper grid to the right-bottom one, taking

poj 3422 Kaka&#39;s Matrix Travels 【最大费用最大流】【好题】

Kaka's Matrix Travels Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8729   Accepted: 3498 Description On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels with SUM = 0. For each travel, Kaka mo

poj 3422 Kaka&#39;s Matrix Travels 费用流

题意: 给一个n*n的矩阵,每次从左上角走到右下角并取走其中的数,求走k次能取到的最大和. 分析: 费用流边的容量有限制的作用,费用有求和的作用,对于每个点只能取一次,容易想到把这个点拆成两个点并连上容量为1,费用为该点数的边.但明显有的流要"跳过"这个点,如何处理呢?可以加一条容量为无穷,费用为0的边,这样不参加这点费用计算的流就可以"跳过"这个点了. 代码: //poj 3422 //sep9 #include <iostream> #include

POJ 3422 Kaka&#39;s Matrix Travels(网络流之费用流)

题目地址:POJ 3422 方法是对每个点i拆点成i'和i'',然后对每个i'和i''连一条费用为该点值,流量为1的边,再连1条费用为0,流量为k-1的边. 然后对每个点与右边下边相邻的点连边,流量均为INF,费用均为0.需要再建一源点与汇点,对于k次只需要在源点与汇点处进行限制即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #inclu