Brief description:
给出一块 n*m
的区域,已知区域中的每个格子都可以放金蛋或者是银蛋。
每个格子放金蛋或银蛋时,可以获得不同的收益,但如果相邻的两个格子放相同的蛋的话,会产生一些代价。(都放金蛋的话产生 g 代价、都放银蛋的话产生 s 代价)。
求一种放置方案,最大化收益。
http://acm.hdu.edu.cn/showproblem.php?pid=3820
最小割、二分图。
const int N = int(1e4) + 9, M = int(N*6) * 2; //struct Network_Flow{ int D[N], hd[N], suc[M], to[M], cap[M]; int n, m, s, t, G, S; inline void ae(int x, int y, int c){ suc[m] = hd[x], hd[x] = m, to[m] = y, cap[m++] = c, suc[m] = hd[y], hd[y] = m, to[m] = x, cap[m++] = 0; } inline void aee(int x, int y, int c){ suc[m] = hd[x], hd[x] = m, to[m] = y, cap[m++] = c, suc[m] = hd[y], hd[y] = m, to[m] = x, cap[m++] = c; } #define v to[i] #define c cap[i] #define f cap[i^1] LL sap(){ LL z=0; static int cnt[N],cur[N],pre[N]; fill(D,D+n,n),fill(cnt,cnt+n,0);cnt[n]=n; int u=s;cur[s]=hd[s];while (D[s]){ #define i cur[u] if (u==t){ int d=INF;for(u=s;u!=t;u=v)checkMin(d,c); z+=d;for(u=s;u!=t;u=v)f+=d,c-=d;u=s; } #undef i int i;for(i=cur[u];i;i=suc[i]){ if(D[u]+1==D[v]&&c){cur[u]=i,cur[v]=hd[v],pre[v]=u,u=v;break;} } if (!i){ if (!--cnt[D[u]])break; D[u]=1;REP_G(i,u)if(c)checkMax(D[u],D[v]);--D[u]; ++cnt[D[u]];if(u==s)cur[u]=hd[u];else u=pre[u]; } } return z; } #undef f #undef c #undef v int r, c, tot; int id(int lv, int i, int j){ return lv*r*c+i*c+j+1; } bool inGrid(int x, int y){ return x >= 0 && y >= 0 && x < r && y < c; } const int NN = 51; int A[NN][NN], B[NN][NN]; void init(){ RD(r, c, G, S); s = 0, t = 2*r*c+1, n = t+1, m = 2; fill(hd, hd+n, 0); tot = 0; REP_2(i, j, r, c) tot += RD(A[i][j]); REP_2(i, j, r, c) tot += RD(B[i][j]); REP_2(i, j, r, c) ae(id(0,i,j),id(1,i,j),INF); REP_2(i, j, r, c) if (i&1^j&1){ ae(s, id(0,i,j), A[i][j]), ae(id(1,i,j), t, B[i][j]); REP(d, 4){ int x = i + dx[d], y = j + dy[d]; if (inGrid(x, y)) ae(id(0,i,j),id(1,x,y),G); } } else{ ae(s, id(0,i,j), B[i][j]), ae(id(1,i,j), t, A[i][j]); REP(d, 4){ int x = i + dx[d], y = j + dy[d]; if (inGrid(x, y)) ae(id(0,i,j),id(1,x,y),S); } } } //} G; int main(){ #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif Rush{ init(); OT(tot - sap()); } }