生活随笔
收集整理的這篇文章主要介紹了
[codevs 1907] 方格取数3
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
[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;
}
總結
以上是生活随笔為你收集整理的[codevs 1907] 方格取数3的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。