记得以前做过这样类似的题,因为那时候求的是来回的最大值,直接使用的dp,而且对费用流并不是很清楚,然后又看到了这道题。。。
对点进行拆分建图,一个点拆为两个点a和b,在a和b之间建一条花费为输入值容量为1的边,然后再建一条花费为0容量为k-1的边,对b点对于其右边和下边都建立一条容量为k花费为0的边,加入超级源点和汇点,花费为0容量为k,由此套模板就可以了!
下面是代码:
/
// File Name: 2195.cpp
// Author: wang
// mail: 1062239606@qq.com
// Created Time: 2013/10/25 19:28:26
/
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <cstring>
#include <cmath>
#include <algorithm>
#include<iostream>
#include<queue>
#include <map>
using namespace std;
typedef long long ll;
#define INF (INT_MAX/10)
#define SQR(x) ((x)*(x))
#define rep(i, n) for (int i=0; i<(n); ++i)
#define repf(i, a, b) for (int i=(a); i<=(b); ++i)
#define repd(i, a, b) for (int i=(a); i>=(b); --i)
#define clr(ar,val) memset(ar, val, sizeof(ar))
#define inf 100000000
#define N 5010
class match{
public:
//s和t要赋值的,并且花费一个为正一个为负刚好抵消的
int s,t;//源点和结束点的,开始为1 的
struct node{
int y,cost,cap,pre;
};
node a[N*1000];
int dis[N];
bool vis[N];
int point[N];
int len,pre[N];
void init()
{
len=0;
memset(pre,-1,sizeof(pre));
}
void addpage(int x,int y,int cap,int cost)
{
a[len].y=y;
a[len].pre=pre[x];
a[len].cap=cap;
a[len].cost=cost;
pre[x]=len++;
}
bool spfa()
{
repf(i,1,t) vis[i]=false,dis[i]=inf;
vis[s]=true; dis[s]=0;
queue<int>q;
q.push(s);
while(!q.empty())
{
int x=q.front(); q.pop();
vis[x]=false;
for(int i=pre[x]; i!=-1; i=a[i].pre)
{
int y=a[i].y;
if(a[i].cap && dis[y]>dis[x]+a[i].cost)
{
point[y]=i;//记录边的
dis[y]=dis[x]+a[i].cost;
if(vis[y]==false)
{
vis[y]=true;
q.push(y);
}
}
}
}
if(dis[t]!=inf) return true;
else return false;
}
int fond()
{
int ans=0;
while(spfa())
{
int Min=INT_MAX;
for(int i=t; i!=s; i=a[point[i]^1].y)//最小的容量,进行扩展的
Min=min(Min,a[point[i]].cap);
for(int i=t; i!=s; i=a[point[i]^1].y)
{
a[point[i]].cap-=Min;
a[point[i]^1].cap+=Min;
ans+=Min*a[point[i]].cost;
}
}
return -ans;
}
};
match sa;
int a[55][55];
int n,m;
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
repf(i,1,n)
repf(j,1,n)
scanf("%d",&a[i][j]);
sa.init();
sa.s=0; sa.t=2*n*n+1;
repf(i,1,n)
repf(j,1,n)
{
int k=(i-1)*n+j;//2*k,2*k-1
sa.addpage(2*k-1,2*k,1,-a[i][j]);
sa.addpage(2*k,2*k-1,0,a[i][j]);
sa.addpage(2*k-1,2*k,m-1,0);
sa.addpage(2*k,2*k-1,0,0);
if(i<n)
sa.addpage(2*k,2*(i*n+j)-1,m,0),
sa.addpage(2*(i*n+j)-1,2*k,0,0);
if(j<n)
sa.addpage(2*k,2*(i*n-n+j+1)-1,m,0),
sa.addpage(2*(i*n-n+j+1)-1,2*k,0,0);
}
sa.addpage(sa.s,1,m,0);
sa.addpage(1,sa.s,0,0);
sa.addpage(2*n*n,2*n*n+1,m,0);
sa.addpage(2*n*n+1,2*n*n,0,0);
printf("%d\n",sa.fond());
}
return 0;
}