[codevs 1907] 方格取数3
来源:互联网 发布:lua map数组 编辑:程序博客网 时间:2024/05/15 00:08
[codevs 1907] 方格取数3
题解:
二分图染色、最大点权独立集。
因为要用到最大独立集的一些思路,故先写了一篇最大独立集的题解:http://blog.csdn.net/qq_21110267/article/details/43371311
最大点权独立集可以类比到最大独立集,同样求解它的对称问题——最小点权覆盖问题(思路见上),点权和-最小点权覆盖=最大点权独立集。
那么怎么求最小点权覆盖呢?
想一想最小割模型,割的性质是不存在一条s-t的路径,我们已经建立了二分图模型,假设u是左侧的结点,v是右侧的结点,那么s-u、u-v、v-t必定有一条在最小割中,如果人为的令u-v不在最小割中(设边权为INF),那么就简化为了s-u、v-t至少一条边在最小割中,正符合了最小点权覆盖中相邻点(u、v)至少一个点被选中,我们把s-u的容量设为点u的权值,v-t的容量设为点t的权值,这样s-u在最小割中就对应着u被选中,而v-t在最小割中就对应着v被选中,这样就把最小点权覆盖问题转化为了最大流问题。
代码:
总时间耗费: 3ms
总内存耗费: 492B
#include<cstdio>#include<iostream>#include<vector>#include<queue>#include<algorithm>using namespace std;const int maxn = 1000 + 10;const int INF = 1000000007;struct Edge {int from, to, cap, flow;};vector<Edge> edges;vector<int> G[maxn];int val[maxn][maxn];void AddEdge(int from, int to, int cap) {edges.push_back((Edge){from, to, cap, 0});edges.push_back((Edge){to, from, 0, 0});int sz = edges.size();G[from].push_back(sz-2);G[to].push_back(sz-1);}int m, n, s, t;int d[maxn], p[maxn], cur[maxn], num[maxn];bool vis[maxn];bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(s); d[s] = 0; vis[s] = 1; 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(!vis[e.to] && e.cap > e.flow) { vis[e.to] = true; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[t];}int DFS(int u, int a) { if(u == t || a == 0) return a; int flow = 0, f; for(int &i = cur[u]; i < G[u].size(); i++) { Edge& e = edges[G[u][i]]; if(d[u] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) { e.flow += f; edges[G[u][i]^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow;}int Maxflow() { int flow = 0; while(BFS()) { memset(cur, 0, sizeof(cur)); flow += DFS(s, INF); } return flow;}int main() {cin >> m >> n;s = 0; t = m * n + 1;int tot = 0;for(int i = 0; i < m; i++)for(int j = 0; j < n; j++) {cin >> val[i][j];tot += val[i][j];}for(int i = 0; i < m; i++)for(int j = 0; j < n; j++) {int u = i*n + j + 1;if((i+j)&1) {if(i > 0) AddEdge(u, u-n, INF);if(j > 0) AddEdge(u, u-1, INF);if(i < m-1) AddEdge(u, u+n, INF);if(j < n-1) AddEdge(u, u+1, INF);AddEdge(s, u, val[i][j]); } else {AddEdge(u, t, val[i][j]);}}int ans = Maxflow();cout << tot - ans << endl;return 0;}
0 0
- [codevs 1907] 方格取数3
- codevs 1907:方格取数3
- CODEVS 1907 方格取数 3
- CodeVS 1907 方格取数 3 (ISAP)
- Codevs 1907 方格取数 3 最小割
- codevs 1907 方格取数 网络流
- codevs-1043 方格取数
- codevs 1043方格取数
- codevs 1227 方格取数
- 【codevs 1043】方格取数
- 【codevs 1902】方格取数3(最小割)
- CODEVS 1227 方格取数 2
- [codevs 1227] 方格取数2
- codevs 1227 方格取数 网络流
- codevs 1227 方格取数2
- 【CodeVS 1227】 方格取数2
- codevs 1227 方格取数2
- codevs动态规划 方格取数
- 【免积分下载csdn资源】
- IOS-- UIView中的坐标转换
- 不越狱安装iPa的原理
- JVM调优总结
- 浅谈DAS、SAN、NAS
- [codevs 1907] 方格取数3
- POJ 3026 Borg Maze(kuangbin带你飞 专题六:最小生成树,完结)
- 垃圾回收器
- [leetcode] Count and Say
- jackson将java对象转换为json字符串
- apache2虚拟主机配置
- Android 平台简介
- Scala初探(三)
- Python核心编程 第十章