题目大意:给出一个三维的点阵,没个点都有可能被切割,代价就是这个点的权值。相邻的切割点的高度差不能超过D,问最小的花费使得上下分开。
思路:很裸的最小割模型,很神的建图。
S->第一层的点,f:INF
所有点->它下面的点,f:INF
一个点的入->一个点的出,f:val[i]
(i,j,k) - > (i - d,j,k),f:INF
最下面一层的点->T:f:INF
然后跑最小割就是答案。
为什么见:http://www.cnblogs.com/zyfzyf/p/4182168.html OTZ ZYF
CODE:
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 130000 #define MAXE 1200000 #define S 0 #define T (MAX - 1) #define INF 0x3f3f3f3f using namespace std; const int dx[] = {0,1,-1,0,0}; const int dy[] = {0,0,0,1,-1}; struct MaxFlow{ int head[MAX],total; int next[MAXE],aim[MAXE],flow[MAXE]; int deep[MAX]; MaxFlow() { total = 1; memset(head,0,sizeof(head)); } void Add(int x,int y,int f) { next[++total] = head[x]; aim[total] = y; flow[total] = f; head[x] = total; } void Insert(int x,int y,int f) { Add(x,y,f); Add(y,x,0); } bool BFS() { static queue<int> q; while(!q.empty()) q.pop(); memset(deep,0,sizeof(deep)); deep[S] = 1; q.push(S); while(!q.empty()) { int x = q.front(); q.pop(); for(int i = head[x]; i; i = next[i]) if(flow[i] && !deep[aim[i]]) { deep[aim[i]] = deep[x] + 1; q.push(aim[i]); if(aim[i] == T) return true; } } return false; } int Dinic(int x,int f) { if(x == T) return f; int temp = f; for(int i = head[x]; i; i = next[i]) if(flow[i] && temp && deep[aim[i]] == deep[x] + 1) { int away = Dinic(aim[i],min(flow[i],temp)); if(!away) deep[aim[i]] = 0; flow[i] -= away; flow[i^1] += away; temp -= away; } return f - temp; } }solver; int P,Q,R,D; int src[50][50][50],num[50][50][50],cnt; int main() { cin >> P >> Q >> R >> D; for(int i = 1; i <= R; ++i) for(int j = 1; j <= P; ++j) for(int k = 1; k <= Q; ++k) { scanf("%d",&src[i][j][k]),num[i][j][k] = ++cnt; solver.Insert(num[i][j][k] << 1,num[i][j][k] << 1|1,src[i][j][k]); } for(int i = 1; i <= P; ++i) for(int j = 1; j <= Q; ++j) { solver.Insert(S,num[1][i][j] << 1,INF); solver.Insert(num[R][i][j] << 1|1,T,INF); } for(int i = 1; i <= R; ++i) for(int j = 1; j <= P; ++j) for(int k = 1; k <= Q; ++k) { if(i != R) solver.Insert(num[i][j][k] << 1|1,num[i + 1][j][k] << 1,INF); for(int d = 1; d <= 4; ++d) { int fx = j + dx[d],fy = k + dy[d]; if(!fx || !fy || fx > P || fy > Q) continue; if(i - D > 0) solver.Insert(num[i][j][k] << 1,num[i - D][fx][fy] << 1,INF); } } int max_flow = 0; while(solver.BFS()) max_flow += solver.Dinic(S,INF); cout << max_flow << endl; return 0; }
时间: 2024-10-24 09:45:32