luogu P1935 [国家集训队]圈地计划 最小割

https://www.luogu.com.cn/blog/I-love-saber/solution-p1935

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 10010, M = 200010, INF = 1e8;
#define int long long
int n, m, S, T;
int c[200][200];
int h[N], e[M], w[M], ne[M], idx;
int q[N], d[N], cur[N];

void add(int a, int b, int c)
{
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
	e[idx] = a, w[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;
}

bool bfs()
{
	int hh = 0, tt = 0;
	memset(d, -1, sizeof d);
	q[0] = S, d[S] = 0, cur[S] = h[S];
	while (hh <= tt)
	{
		int t = q[hh ++ ];
		for (int i = h[t]; ~i; i = ne[i])
		{
			int ver = e[i];
			if (d[ver] == -1 && w[i])
			{
				d[ver] = d[t] + 1;
				cur[ver] = h[ver];
				if (ver == T)  return true;
				q[ ++ tt] = ver;
			}
		}
	}
	return false;
}

int find(int u, int limit)
{
	if (u == T) return limit;
	int flow = 0;
	for (int i = cur[u]; ~i && flow < limit; i = ne[i])
	{
		cur[u] = i;  // 当前弧优化
		int ver = e[i];
		if (d[ver] == d[u] + 1 && w[i])
		{
			int t = find(ver, min(w[i], limit - flow));
			if (!t) d[ver] = -1;
			w[i] -= t, w[i ^ 1] += t, flow += t;
		}
	}
	return flow;
}

int dinic()
{
	int r = 0, flow;
	while (bfs()) while (flow = find(S, INF)) r += flow;
	return r;
}
int num(int a,int b)
{
	return m*(a-1)+b;
}
signed main()
{
	cin>>n>>m;
	memset(h, -1, sizeof h);
	S=0,T=N-1;
	int sum=0;
	for(int i=1; i<=n; i++)
	{
		for(int j=1; j<=m; j++)
		{
			int a;
			cin>>a;
			if ((i+j)&1)add(S,num(i,j),a);
			else add(num(i,j),T,a);
			sum+=a;
		}
	}
	for(int i=1; i<=n; i++)
	{
		for(int j=1; j<=m; j++)
		{
			int a;
			cin>>a;
			if ((i+j)&1)add(num(i,j),T,a);
			else add(S,num(i,j),a);
			sum+=a;
		}
	}
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
			scanf("%d",&c[i][j]);
	int tx[]= {0,-1,0,1},ty[]= {1,0,-1,0};
	for(int i=1; i<=n; i++)
	{
		for(int j=1; j<=m; j++)
		{
			for(int k=0; k<4; k++)
			{
				int xx=i+tx[k],yy=j+ty[k];
				if (xx<=0||xx>n)continue;
				if (yy<=0||yy>m)continue;
				add(num(i,j),num(xx,yy),c[i][j]+c[xx][yy]);
				sum+=c[i][j];
			}
		}
	}
	cout<<sum-dinic();

	return 0;
}
posted @ 2020-10-28 19:42  晴屿  阅读(86)  评论(0编辑  收藏  举报