网络流24题(09)方格取数问题(最大点权独立集 + 最小割最大流)
2013-04-20 21:37
459 查看
题意:
在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。
思路:
1. 不清楚何为“最小点权覆盖集”和“最大点权独立集”概念的请看这篇文章《最小割模型在信息学竞赛中的应用》;
2. “最小点权覆盖集”和“最大点权独立集”是两个互补的概念,我们可以利用最小割求一个二分图的最小点权覆盖集;
3. 把黑白相间染色,黑色部分为 X 集,白色部分为 Y 集,s 向 X 中的点引弧, Y 向 t 引弧,容量为 点权的大小;
X 和 Y 中相邻的点由 X 向 Y 引弧,容量为无穷大,这么做的目的是为了让割边仅在 <s, X> 或 <Y, t> 中;
4. 之所以这么做,是因为我们要求这个图中的“最大点权独立集”,依照其概念可以知道:任意两点不相邻<=>任意两点构成的边不在图中;
5. 求上面网络的最大流,并且根据最小割最大流定理,再根据我们的建图,最大流->最小割->最小点权覆盖。输出 = 总点权 - 最大流;
在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。
思路:
1. 不清楚何为“最小点权覆盖集”和“最大点权独立集”概念的请看这篇文章《最小割模型在信息学竞赛中的应用》;
2. “最小点权覆盖集”和“最大点权独立集”是两个互补的概念,我们可以利用最小割求一个二分图的最小点权覆盖集;
3. 把黑白相间染色,黑色部分为 X 集,白色部分为 Y 集,s 向 X 中的点引弧, Y 向 t 引弧,容量为 点权的大小;
X 和 Y 中相邻的点由 X 向 Y 引弧,容量为无穷大,这么做的目的是为了让割边仅在 <s, X> 或 <Y, t> 中;
4. 之所以这么做,是因为我们要求这个图中的“最大点权独立集”,依照其概念可以知道:任意两点不相邻<=>任意两点构成的边不在图中;
5. 求上面网络的最大流,并且根据最小割最大流定理,再根据我们的建图,最大流->最小割->最小点权覆盖。输出 = 总点权 - 最大流;
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> #include <vector> using namespace std; const int MAXN = 50*50; const int INFS = 0x7FFFFFFF; struct edge { int from, to, cap, flow; edge(int _from, int _to, int _cap, int _flow) : from(_from), to(_to), cap(_cap), flow(_flow) {} }; class Dinic { public: void initdata(int n, int s, int t) { this->n = n, this->s = s, this->t = t; edges.clear(); for (int i = 0; i < n; i++) G[i].clear(); } void addedge(int u, int v, int cap) { edges.push_back(edge(u, v, cap, 0)); edges.push_back(edge(v, u, 0, 0)); G[u].push_back(edges.size() - 2); G[v].push_back(edges.size() - 1); } bool BFS() { for (int i = 0; i < n; i++) vis[i] = false, d[i] = 0; queue<int> Q; Q.push(s); vis[s] = true; while (!Q.empty()) { int x = Q.front(); Q.pop(); for (int i = 0; i < G[x].size(); i++) { edge& e = edges[G[x][i]]; if (e.cap > e.flow && !vis[e.to]) { vis[e.to] = true; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[t]; } int DFS(int x, int aug) { if (x == t || aug == 0) return aug; int flow = 0; for (int i = 0; i < G[x].size(); i++) { edge& e = edges[G[x][i]]; if (d[e.to] == d[x] + 1) { int f = DFS(e.to, min(aug, e.cap - e.flow)); if (f <= 0) continue; e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; aug -= f; if (aug == 0) break; } } return flow; } int maxflow() { int flow = 0; while (BFS()) { flow += DFS(s, INFS); } return flow; } private: vector<edge> edges; vector<int> G[MAXN]; int n, s, t, d[MAXN]; bool vis[MAXN]; }; Dinic dc; int row, col; int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1}; bool check(int x, int y) { if (1 <= x && x <= row && 1 <= y && y <= col) { return true; } return false; } int main() { scanf("%d%d", &row, &col); int sum = 0; int s = 0, t = row*col + 1; dc.initdata(t + 1, s, t); for (int i = 1; i <= row; i++) { for (int j = 1; j <= col; j++) { int a; scanf("%d", &a); sum += a; if ((i+j) & 1) dc.addedge((i-1)*col+j, t, a); else { dc.addedge(s, (i-1)*col+j, a); for (int k = 0; k < 4; k++) { int x = i + dir[k][0]; int y = j + dir[k][1]; if (check(x, y)) dc.addedge((i-1)*col+j, (x-1)*col+y, INFS); } } } } printf("%d\n", sum - dc.maxflow()); return 0; }
相关文章推荐
- [网络流24题] 09 方格取数问题 (二分图点权最大独立集,最小割)
- 【网络流二十四题 方格取数问题】【二分图点权最大独立集->最小割】
- 线性规划与网络流24题之方格取数问题 二分图点权最大独立集
- [网络流24题] 方格取数问题 (最大权独立集---网络最小割)
- nefu482方格取数【最大点权独立集】网络流24题
- 独立最小【网络流第五弹】最大点权独立集 ——HDU 1569 方格取数(2)
- 网络流与线性规划24题09方格取数问题
- loj6226「网络流 24 题」骑士共存问题(二分图最大点独立集,最小割)
- 网络流24题(03)最小路径覆盖问题(二分图匹配 + 最大流)
- 线性规划与网络流24题の9 方格取数(二分图点权最大独立集)
- 网络流24题09方格取数问题
- 线性规划与网络流24题●09方格取数问题&13星际转移问题
- [网络流24题] 方格取数问题 (最大点权独立集)
- 【网络流24题】No.9 方格取数问题 (二分图点权最大独立集)
- 网络流24题(05)魔术球问题(最小路径覆盖 + 最大流)
- 【网络流二十四题 骑士共存问题】【二分图点权最大独立集->最小割】
- luogu2774 方格取数问题(最小割)网络流24题:9
- 线性规划与网络流24题の24 骑士共存问题 (二分图最大独立集)
- hdoj 1569 方格取数(2) 【最小割】 【最大点权独立集】
- 匹配问题(最大匹配,最小覆盖,最大独立集) 欢迎大家来讨论