hdu1565 方格取数(1)--最大点权独立集 & Dinic

来源:互联网 发布:电极编程 编辑:程序博客网 时间:2024/06/09 00:25

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1565


题意:

先设置一个源点(0)和一个汇点( n*n+1),一开始初始化的时候把源点到所有 (i+j)%2 ==1的格子全部给个值,

然后初始化把汇点到所有 (i+j) %2 == 0的格子也给个值,值就是这个格子数字。还有,二维数组flow[i][j]用来标记边。然后求最大点权独立集即可。

最大点权独立集=总权值-最小点权覆盖集。
最小点权覆盖集=图的最小割值=最大流。


#define _CRT_SECURE_NO_DEPRECATE#include<iostream>#include<algorithm>#include<queue>using namespace std;const int INF = 9999999999;int chess[25][25];int flow[25 * 25][25 * 25];int d[25 * 25];int n;int sum;int s, t;int dir[4][2] = { 0,1,-1,0,0,-1,1,0 };bool bfs(){memset(d, 0, sizeof(d));queue<int> Q;Q.push(s);d[s] = 1;while (!Q.empty()){int u = Q.front();Q.pop();for (int v = 1; v <= n*n + 1; v++){if (flow[u][v] > 0 && d[v] == 0){d[v] = d[u] + 1;Q.push(v);}}}return d[t] != 0;}int dfs(int u, int w){if (u == t)return w;int ans = 0;for (int v = 0; v <= n*n + 1; v++){if (flow[u][v] > 0 && d[v] == d[u] + 1){int x = dfs(v, min(w - ans, flow[u][v]));//if (x){ans += x;flow[u][v] -= x;flow[v][u] += x;if (ans == w)return w;}}}if (ans == 0)d[u] = 0;return ans;}int dinic(){int ans = 0;int p;while (bfs())while (p = dfs(s, INF))ans += p;return ans;}int main(){while (~scanf("%d", &n)){sum = 0;memset(flow, 0, sizeof(flow));for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){scanf("%d", &chess[i][j]);sum += chess[i][j];if ((i + j) % 2 == 0)flow[0][(i - 1)*n + j] = chess[i][j];elseflow[(i - 1)*n + j][n*n + 1] = chess[i][j];}}for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){for (int k = 0; k < 4; k++){int x = i + dir[k][0];int y = j + dir[k][1];if (x >= 1 && x <= n&&y >= 1 & y <= n && (i + j) % 2 == 0)//注意只有与s点直接相邻的才可以flow[(i - 1)*n + j][(x - 1)*n + y] = INF;}}}s = 0;t = n*n + 1;printf("%d\n", sum - dinic());}return 0;}


1 0