【wikioi1227】 方格取數 2
阿新 • • 發佈:2019-02-08
#include<cstdio> #include<cstring> #include<iostream> #define INF 0x7fffffff #define N 6001 #define M 1000010 using namespace std; struct data{ int from,to,v,c,next; }e[M]; long long ans; int n,k,dis[N],head[N],from[N],q[M],cnt=1; bool inq[N]; void insert(int u,int v,int w,int c){ e[++cnt].from=u; e[cnt].to=v; e[cnt].v=w; e[cnt].c=c; e[cnt].next=head[u]; head[u]=cnt; } void ins(int u,int v,int w,int c){ insert(u,v,w,c); insert(v,u,0,-c); } bool spfa(){ int t=0,w=1,i,now; memset(dis,-1,sizeof(dis)); q[0]=0;inq[0]=1;dis[0]=0; while(t<w){ now=q[t++];i=head[now]; while(i){ if(e[i].v>0&&dis[now]+e[i].c>dis[e[i].to]){ dis[e[i].to]=dis[now]+e[i].c; from[e[i].to]=i; if(!inq[e[i].to]){ q[w++]=e[i].to;inq[e[i].to]=true; } } i=e[i].next; inq[now]=false; } } if(dis[6000]==-1)return false; else return true; } void mincf(){ int i=from[6000],sum=INF; while(i){ sum=min(sum,e[i].v); i=from[e[i].from]; } i=from[6000]; while(i){ e[i].v-=sum; e[i^1].v+=sum; ans+=sum*e[i].c; i=from[e[i].from]; } } int main(){ scanf("%d %d",&n,&k); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ int x;scanf("%d",&x); ins((i-1)*n+j,(i-1)*n+j+n*n,1,x); ins((i-1)*n+j,(i-1)*n+j+n*n,k,0); if(j<n)ins((i-1)*n+j+n*n,(i-1)*n+j+1,k,0); if(i<n)ins((i-1)*n+j+n*n,i*n+j,k,0); } ins(0,1,k,0);ins(2*n*n,6000,k,0); while(spfa())mincf(); printf("%lld",ans); return 0; }