【 bzoj 2132 】GDOI圈地计划 - 最小割
2016-02-15 15:37
225 查看
考虑黑白染色成二分图。我们要的是最大收益,那么就应该是删掉最小的一些收益。对于白点W,连S→W,W→T,容量分别为A收入和B收入,黑点则反过来,然后有关系的双向连上容量为C的和的边。
这样割掉之后就行了。
这样割掉之后就行了。
#include <bits/stdc++.h> using namespace std; #define rep(i,a,b) for (int i = a , _ = b ; i <= _ ; i ++) #define per(i,a,b) for (int i = a , _ = b ; i >= _ ; i --) #define fore(i,u) for (int i = head[u] ; i ; i = nxt[i]) inline int rd() { char c = getchar(); while (!isdigit(c)) c = getchar() ; int x = c - '0'; while (isdigit(c = getchar())) x = x * 10 + c - '0'; return x; } const int inf = 0x7fffffff; const int maxn = 10007; const int maxm = 160007; const int fx[] = {0 , 0 , 1 , -1}; const int fy[] = {1 , -1 , 0 , 0}; typedef int arr[maxn]; typedef int adj[maxm]; typedef int mat[107][107]; arr head , dis , cur; adj to , nxt , cap , flow; mat a , b , c; queue<int> Q; int n , m , ett , ans , S ,T; inline int id(int x , int y) { return (x - 1) * m + y ; } void input() { n = rd() , m = rd() , ett = 1; memset(c , -1 , sizeof c); rep (i , 1 , n) rep (j , 1 , m) a[i][j] = rd(); rep (i , 1 , n) rep (j , 1 , m) b[i][j] = rd(); rep (i , 1 , n) rep (j , 1 , m) c[i][j] = rd(); } inline void ins(int u , int v , int c) { // printf("%d %d %d\n" , u , v , c); to[++ ett] = v , nxt[ett] = head[u] , cap[ett] = c , head[u] = ett; to[++ ett] = u , nxt[ett] = head[v] , cap[ett] = 0 , head[v] = ett; } inline bool bfs() { rep (i , 1 , T) dis[i] = 0; dis[S] = 1 , Q.push(S); while (!Q.empty()) { int u = Q.front() ; Q.pop(); fore (i , u) if (cap[i] > flow[i]) { int v = to[i]; if (!dis[v]) { dis[v] = dis[u] + 1; Q.push(v); } } } return dis[T] > 0; } int dfs(int u , int a) { if (u == T || !a) return a; int ret = 0 , f; for (int&i = cur[u] ; i ; i = nxt[i]) { int v = to[i]; if (dis[v] == dis[u] + 1 && (f = dfs(v , min(a , cap[i] - flow[i])))) { flow[i] += f , flow[i ^ 1] -= f , a -= f , ret += f; if (!a) break; } } return ret; } int max_flow() { int ret = 0; while (bfs()) { rep (i , 1 , T) cur[i] = head[i]; ret += dfs(S , inf); } return ret; } void solve() { S = n * m + 1 , T = n * m + 2; rep (i , 1 , n) rep (j , 1 , m) { if (i + j & 1) ins(S , id(i , j) , a[i][j]) , ins(id(i , j) , T , b[i][j]); else ins(S , id(i , j) , b[i][j]) , ins(id(i , j) , T , a[i][j]); ans += a[i][j] + b[i][j]; if (!(i + j & 1)) continue; rep (d , 0 , 3) { int x = i + fx[d] , y = j + fy[d]; if (c[x][y] == -1) continue; ins(id(i , j) , id(x , y) , c[i][j] + c[x][y]); ins(id(x , y) , id(i , j) , c[i][j] + c[x][y]); ans += c[i][j] + c[x][y]; } } // printf("%d\n" , ans); ans -= max_flow(); printf("%d\n" , ans); } int main() { #ifndef ONLINE_JUDGE freopen("data.txt" , "r" , stdin); #endif input(); solve(); return 0; }
相关文章推荐
- IOS开发证书显示“此证书的签发者无效”解决方法
- [学习笔记]Apollo Flash Block
- Leetcode解题思路总结(Medium)
- 简单描述UIView 和 CALayer的区别
- 以后可以看的资源01
- 类式继承
- 使用urlrewritefilter发现部分请求url报404
- REST详解
- JS鼠标事件大全(转)
- sqlserver2012附加数据库报错--无法打开物理文件 XXX.mdf",操作系统错误 5:"5(拒绝访问。)"
- [从头学数学] 第89节 数学广角--找次品
- garbage collection is no longer supported
- poj3280
- 易语言
- (转)WEB第三方打印控件[ASP.NET常用工具]
- 做百度钱包相关调查问卷有感
- Oracle数据库导入、导出dmp文件
- Qt信号槽写法
- hrbust 2147 哈理工oj 经理办公室【水题】
- [学习笔记] KEIL 如何把data,code放到指定地址