萌新刚学Dinic,36分求助
查看原帖
萌新刚学Dinic,36分求助
510555
ImposterAnYu楼主2023/1/31 17:43
#include<bits/stdc++.h>
#define int1 int
#define N 10005
#define M 160005
using namespace std;
int1 n,m,nm,i,j,x,y,t,ta[N],la[M],no[M],to[M],dep[N],bs,w[M],ans,s,a[N],bla,whi,bl[N],wh[N],sum;
bool b;
queue<int1> q;
void C(){//关同步。 
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	return ;
}
void add_edge(int1 a,int1 b,int1 s){//表示连一条从a走向b的有向边。 
	la[++bs] = ta[a],ta[a] = bs,no[bs] = a,to[bs] = b,w[bs] = s;
	return ;
}
void ae(int1 a,int1 b,int1 s){//建边和建反向边。 
	add_edge(a,b,s),add_edge(b,a,0);
	return ;
}
bool bfs(int1 x){//BFS求深度。 
	q.push(x);
	memset(dep,0,sizeof(dep));
	dep[x] = 1;
	while(!q.empty()){
		x = q.front();
		q.pop();
		for(int1 i = ta[x]; i; i = la[i]){
			y = to[i];
			if(!dep[y] && w[i] > 0){
				dep[y] = dep[x] + 1;
				q.push(y);
			}
		}
	}
	return (dep[t] != 0);
}
int1 dfs(int1 x,int1 s){//DFS跑最大流。 
	if(x == t){
		return s;
	}
	int1 tj = dep[x] + 1;
	for(int1 i = ta[x]; i; i = la[i]){
		y = to[i];
		if(dep[y] == tj && w[i] > 0){
			int1 d = dfs(y,min(s,w[i]));
			if(d > 0){
				w[i] -= d,w[i ^ 1] += d;
				return d;
			}
		}
	}
	return 0; 
}
int main(){
	C();
	cin >> n >> m;
	t = nm = n * m + 1;//源点编号为0,汇点编号为nm+1。 
	for(i = 1; i <= n; i++){
		for(j = 1; j <= m; j++){
			int1 d = (i - 1) * m + j;
			cin >> a[d];
			sum += a[d];
			if((i + j) & 1){//黑点。 
				ae(0,d,a[d]);
				if(i < n){
					ae(d,d + m,1145141919);
				}
				if(i > 1){
					ae(d,d - m,1145141919);
				}
				if(j < m){
					ae(d,d + 1,1145141919);
				}
				if(j > 1){
					ae(d,d - 1,1145141919);
				}
			}else{//白点。 
				ae(d,nm,a[d]);
			}
		}
	}
	while(bfs(0)){//Dinic。 
		while(s = dfs(0,1145141919)){
			ans += s;
		}
	}
	cout<< sum - ans << endl;
	return 0;
}
2023/1/31 17:43
加载中...