P4313 【模板】最小割多选一模型

题目地址


易错点:


#include<bits/stdc++.h>
using namespace std;
const int MAXN=105*105*3;
const int INF=2e9;
struct Edge{
    int from,to,w,nxt;
}e[MAXN*10];
int head[MAXN],edgeCnt=1;
void addEdge(int u,int v,int w){
	e[++edgeCnt].from=u;
	e[edgeCnt].to=v;
	e[edgeCnt].w=w;
	e[edgeCnt].nxt=head[u];
	head[u]=edgeCnt;
}
int n,m;
int getHash(int i,int j){
	return (i-1)*m+j;
}
int s,t;
int fx[5]={1,-1,0,0,0};
int fy[5]={0,0,1,-1,0};
void doit(int x,int y){
    for(int i=0;i<5;i++){
        int nx=x+fx[i],ny=y+fy[i];
        if(nx<1||ny<1||nx>n||ny>m)continue;
        int nowU=getHash(x,y),nowV=getHash(nx,ny);
        addEdge(n*m+nowV,nowU,INF);
        addEdge(nowU,n*m+nowV,0);
        addEdge(nowU,2*n*m+nowV,INF);
        addEdge(2*n*m+nowV,nowU,0);
    }
}
int d[MAXN];
bool bfs(){
    memset(d,0,sizeof(d));
    queue<int> q;
    q.push(s);d[s]=1;
    while(!q.empty()){
        int nowV=q.front();q.pop();
        for(int i=head[nowV];i;i=e[i].nxt){
            int nowNode=e[i].to;
            if(!d[nowNode]&&e[i].w){
                d[nowNode]=d[nowV]+1;
                if(nowNode==t)return 1;
                q.push(nowNode);
            }
        }
    }
    return 0;
}
int Dinic(int x,int flow){
    if(x==t)return flow;
    int rest=flow;
    for(int i=head[x];i&&rest;i=e[i].nxt){
        int nowV=e[i].to;
        if(d[nowV]==d[x]+1&&e[i].w){
            int k=Dinic(nowV,min(rest,e[i].w));
            if(!k)d[nowV]=0;
            e[i].w-=k,e[i^1].w+=k;
            rest-=k;
        }
    }
    return flow-rest;
}
int main(){
	scanf("%d%d",&n,&m);t=3*n*m+1;
	int art,sci,saa,sas; 
	int sum=0;
    for(int i=1;i<=n;i++){
    	for(int j=1;j<=m;j++){
    		int nowV=getHash(i,j);
    		scanf("%d",&art);
			addEdge(s,nowV,art);
			addEdge(nowV,s,0);
			sum+=art;
		}
	}
    for(int i=1;i<=n;i++){
    	for(int j=1;j<=m;j++){
    		int nowV=getHash(i,j);
    		scanf("%d",&sci);
			addEdge(nowV,t,sci);
			addEdge(t,nowV,0);
			sum+=sci;
		}
	}
    for(int i=1;i<=n;i++){
    	for(int j=1;j<=m;j++){
    		int nowV=getHash(i,j);
    		scanf("%d",&saa);
			addEdge(s,n*m+nowV,saa);
			addEdge(n*m+nowV,s,0);
			sum+=saa;
		}
	}
    for(int i=1;i<=n;i++){
    	for(int j=1;j<=m;j++){
    		int nowV=getHash(i,j);
    		scanf("%d",&sas);
			addEdge(2*n*m+nowV,t,sas);
			addEdge(t,2*n*m+nowV,0);
			sum+=sas;
		}
	}
    for(int i=1;i<=n;i++){
    	for(int j=1;j<=m;j++){
			 doit(i,j);
		}
	}
    int ans=0;
    while(bfs())
    	ans+=Dinic(s,INF);
    printf("%d",sum-ans);
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值