BZOJ 3144: [Hnoi2013]切糕 [最小割]

3144: [Hnoi2013]切糕

题意:略


省选之前口胡过~

每个点拆成r个点

题目要求

\[\mid f(x,y) - f(x',y') \mid \le D \]

我们可以对每个点都考虑上界,这样其实也把下界考虑了

\((x,y,k)\)\((x,y,k+1)\)\(val(x,y,k)\)的边,向\((x,y,k-D)\)连inf

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=7e4+5, M=1e6+5, INF=1e9;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

int n, m, r, d, val, nm, s, t;
inline int id(int i, int j, int k) {return (i-1)*m+j + (k-1)*nm;}

namespace mf {
	struct edge{int v, ne, c, f;} e[M];
	int cnt=1, h[N];
	inline void ins(int u, int v, int c) {
		e[++cnt]=(edge){v, h[u], c, 0}; h[u]=cnt;
		e[++cnt]=(edge){u, h[v], 0, 0}; h[v]=cnt;
	}
	
	int q[N], head, tail, d[N], vis[N];
	bool bfs() {
		memset(vis, 0, sizeof(vis));
		head=tail=1;
		q[tail++]=s; vis[s]=1; d[s]=0;
		while(head != tail) {
			int u = q[head++];
			for(int i=h[u];i;i=e[i].ne) 
				if(!vis[e[i].v] && e[i].c > e[i].f) {
					vis[e[i].v] = 1; d[e[i].v] = d[u]+1;
					q[tail++] = e[i].v;
					if(e[i].v == t) return true;
				}
		}
		return false;
	}
	int cur[N];
	int dfs(int u, int a) {
		if(u==t || a==0) return a;
		int flow=0, f;
		for(int &i=cur[u];i;i=e[i].ne) 
			if(d[e[i].v] == d[u]+1 && (f = dfs(e[i].v, min(a, e[i].c-e[i].f)) ) > 0) {
				flow += f;
				e[i].f += f;
				e[i^1].f -= f;
				a -= f;
				if(a == 0) break;
			}
		if(a) d[u] = -1;
		return flow;
	}
	int dinic() {
		int flow=0;
		while(bfs()) { 
			for(int i=s; i<=t; i++) cur[i] = h[i];
			flow += dfs(s, INF); 
		}
		return flow;
	}
} using mf::ins;

int main() {
	freopen("in", "r", stdin);
	n=read(); m=read(); r=read(); d=read(); nm = n*m;
	s=0; t=n*m*r+1;
	for(int k=1; k<=r; k++) 
		for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) {
			val=read(); int now = id(i, j, k);
			if(k != r) ins(now, now+nm, val);
			else ins(now, t, val);
			if(k-d >= 1) {
				if(i != 1) ins(now, id(i-1, j, k-d), INF);
				if(i != n) ins(now, id(i+1, j, k-d), INF);
				if(j != 1) ins(now, id(i, j-1, k-d), INF);
				if(j != m) ins(now, id(i, j+1, k-d), INF);
			}
		}
	for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) ins(s, id(i, j, 1), INF);
	int ans = mf::dinic();
	printf("%d", ans);
}

posted @ 2017-04-13 16:28  Candy?  阅读(335)  评论(0编辑  收藏  举报