方格取数加强版 题解

Posted skylight

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了方格取数加强版 题解相关的知识,希望对你有一定的参考价值。

因为一个点的贡献只能算一次,把点拆成2个点即可,连一条流量为(1),费用为这个点的值,然后再连一条流量为(+infty),费用为(0)的边,接下来对于每个点向它下方和它右方的点连一条流量为(+infty),费用为(0)的边即可。算最大费用,边权取反。

#include <bits/stdc++.h>
int n,k,S,T,mincost;
int a[111][111];
int head[1000000],tot=1;
struct edge{int to,nxt,flow,cost;}e[1000000];
int dis[6600],vis[6600],flow[6600],pren[6600],pree[6600];
std::queue<int>q;
int GN(int x,int y){
  return x*n-n+y;
}
void add(int x,int y,int flow,int w){
	e[++tot]={y,head[x],flow,w};
	head[x]=tot;
	e[++tot]={x,head[y],0,-w};
	head[y]=tot;
}
bool spfa(){
	memset(dis,0x3f,sizeof dis);
	memset(vis,0,sizeof vis);
	memset(flow,0x3f,sizeof flow);
	q.push(S);
	vis[S]=1;
	dis[S]=0;
	while(!q.empty()){
		int x=q.front();
		q.pop();
		vis[x]=0;
		for(int i=head[x];i;i=e[i].nxt){
			int y=e[i].to;
			vis[x]=0;
			if(e[i].flow&&dis[y]>dis[x]+e[i].cost){
				dis[y]=dis[x]+e[i].cost;
				flow[y]=std::min(flow[x],e[i].flow);
				pren[y]=x;
				pree[y]=i;
				if(!vis[y]){
					vis[y]=1;
					q.push(y);
				}
			}
		}
	}
	return dis[T]!=0x3f3f3f3f;
}
void dinic(){
	while(spfa()){
		mincost-=dis[T]*flow[T];
		for(int i=T;i!=S;i=pren[i]){
			e[pree[i]].flow-=flow[T];
			e[pree[i]^1].flow+=flow[T];
		}
	}
}
main(){
	scanf("%d%d",&n,&k);
	S=2*n*n+1,T=S+1;
	for(int i=1;i<=n;++i)
	  for(int j=1;j<=n;++j)
			scanf("%d",&a[i][j]);
  for(int i=1;i<=n;++i)
    for(int j=1;j<=n;++j){
    	add(GN(i,j),GN(i,j)+n*n,1,-a[i][j]);
    	add(GN(i,j),GN(i,j)+n*n,0x3f3f3f3f,0);
    	if(i<n)add(GN(i,j)+n*n,GN(i+1,j),k,0);
    	if(j<n)add(GN(i,j)+n*n,GN(i,j+1),k,0);
    }
  add(S,GN(1,1),k,0);
  add(GN(n,n)+n*n,T,k,0);
  n=T;
	dinic();
	printf("%d
",mincost);
	return 0;
}

以上是关于方格取数加强版 题解的主要内容,如果未能解决你的问题,请参考以下文章

题解luogu2045 方格取数游戏加强版

Luogu P2045 方格取数加强版 题解

[luoguP2045] 方格取数加强版(最小费用最大流)

Luogu1006 传纸条 与 Luogu P2045方格取数加强版 (费用流)

P2045 方格取数加强版

poj 3422 洛谷P2045 K取方格数(方格取数加强版)