BZOJ2132 圈地计划
来自y_immortal学长的网络流推荐2333
建模比较神仙qwq
首先可以建立最小割模型 ->二选一
就是我们处理不同的贡献不好处理 那么我们考虑怎么把它变成相同的贡献
对于原图我们进行黑白染色 然后如果一个点属于T集我们让它反色就可以做到相同的有贡献
那么很明显这个贡献是双向的 对于两个点之间的贡献是相加的
所以我们这样做最小割就可以辣~
代码。
//Love and Freedom.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define inf 20021225
#define ll long long
#define M 200000
#define N 30000
using namespace std;
struct edge{int to,lt,f;}e[M];
int in[N],cnt=1,dep[N];
int s,t;
void add(int x,int y,int f)
{
e[++cnt].to = y; e[cnt].lt = in[x]; e[cnt].f = f; in[x] = cnt;
e[++cnt].to = x; e[cnt].lt = in[y]; e[cnt].f = 0; in[y] = cnt;
}
queue<int> q;
bool bfs()
{
while(!q.empty()) q.pop();
memset(dep,0,sizeof(dep));
dep[s] = 1; q.push(s);
while(!q.empty())
{
int x = q.front(); q.pop();
for(int i=in[x];i;i=e[i].lt)
{
int y = e[i].to;
if(!dep[y] && e[i].f)
{
dep[y] = dep[x]+1; q.push(y);
if(dep[t]) return true;
}
}
}
return false;
}
int dfs(int x,int f)
{
if(x==t||!f) return f;
int cur = f;
for(int i=in[x];i;i=e[i].lt)
{
int y = e[i].to;
if(dep[y] == dep[x]+1 && e[i].f)
{
int flow = dfs(y,min(cur,e[i].f));
e[i].f -= flow; e[i^1].f += flow;
cur -= flow; if(cur==0) return f;
}
}
dep[x] = -1;
return f-cur;
}
int dinic()
{
int ans = 0;
while(bfs()) ans+=dfs(s,inf);
return ans;
}
int n,m;
int id(int x,int y)
{
return (x-1)*m + y;
}
int a[101][101];
int b[101][101];
int c[101][101];
int xx[4] = {0,0,1,-1};
int yy[4] = {1,-1,0,0};
int main()
{
int fin = 0;
scanf("%d%d",&n,&m);
s = n*m*2; t = s+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
if((i+j)&1) add(s,id(i,j),a[i][j]);
else add(id(i,j),t,a[i][j]);
fin+=a[i][j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&b[i][j]);
if((i+j)&1) add(id(i,j),t,b[i][j]);
else add(s,id(i,j),b[i][j]);
fin+=b[i][j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&c[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<4;k++)
{
int x = i+xx[k], y = j+yy[k];
if(x<1||y<1||x>n||y>m) continue;
int val = c[i][j] + c[x][y];
add(id(i,j),id(x,y),val);
fin+=c[i][j];
}
printf("%d\n",fin-dinic());
return 0;
}