hdu 1569 方格取数(2) (最大流最小割)
2012-09-19 23:14
323 查看
题解:开始想到DP,但数据比较大,用DP会超时。于是将它转化为最小割问题,增加一个源点和一个汇点,把i+j为偶数的节点与源点s相连,权值为棋盘上对应位置的值,其它的节点与汇点t相连,权值还是棋盘上对应位置的值,相邻的节点相连的权值记为无穷大,再根据最大流最小割定理求一遍最大流,答案即为棋盘上所有点的权值-最大流。
代码:
代码:
#include <stdio.h> #include <string.h> #define N 10010 #define M 400010 const int inf = 0x3f3f3f3f; struct E { int to, frm, nxt, cap; }edge[M]; int head ,e,n,m,src,des; int dep , gap ; void addedge(int u, int v, int w) { edge[e].frm = u; edge[e].to = v; edge[e].cap = w; edge[e].nxt = head[u]; head[u] = e++; edge[e].frm = v; edge[e].to = u; edge[e].cap = 0; edge[e].nxt = head[v]; head[v] = e++; } int que ; void BFS() { memset(dep, -1, sizeof(dep)); memset(gap, 0, sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; dep[des] = 0; que[rear++] = des; int u, v; while (front != rear) { u = que[front++]; front = front%N; for (int i=head[u]; i!=-1; i=edge[i].nxt) { v = edge[i].to; if (edge[i].cap != 0 || dep[v] != -1) continue; que[rear++] = v; rear = rear % N; ++gap[dep[v] = dep[u] + 1]; } } } int cur ,stack ; int Sap() { int res = 0; BFS(); int top = 0; memcpy(cur, head, sizeof(head)); int u = src, i; while (dep[src] < n*m+1) { if (u == des) { int temp = inf, inser = n; for (i=0; i!=top; ++i) if (temp > edge[stack[i]].cap) { temp = edge[stack[i]].cap; inser = i; } for (i=0; i!=top; ++i) { edge[stack[i]].cap -= temp; edge[stack[i]^1].cap += temp; } res += temp; top = inser; u = edge[stack[top]].frm; } if (u != des && gap[dep[u] -1] == 0) break; for (i = cur[u]; i != -1; i = edge[i].nxt) if (edge[i].cap != 0 && dep[u] == dep[edge[i].to] + 1) break; if (i != -1) { cur[u] = i; stack[top++] = i; u = edge[i].to; } else { int min = n*m+3; for (i = head[u]; i != -1; i = edge[i].nxt) { if (edge[i].cap == 0) continue; if (min > dep[edge[i].to]) { min = dep[edge[i].to]; cur[u] = i; } } --gap[dep[u]]; ++gap[dep[u] = min + 1]; if (u != src) u = edge[stack[--top]].frm; } } return res; } int main() { int i,j,c; while(scanf("%d%d",&n,&m)!=EOF) { memset(head,-1,sizeof(head)); src=0,des=n*m+1; int sum=0; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { scanf("%d",&c); sum+=c; int num=(i-1)*m+j; if((i+j)%2) { addedge(src,num,c); if(i>1) addedge(num,num-m,inf); if(i<n) addedge(num,num+m,inf); if(j>1) addedge(num,num-1,inf); if(j<m) addedge(num,num+1,inf); } else addedge(num,des,c); } printf("%d\n",sum-Sap()); } return 0; }
相关文章推荐
- HDU 1569 方格取数(2)(最大流最小割の最大权独立集)
- hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)
- HDU-1569 方格取数(2) 最小割最大流
- 独立最小【网络流第五弹】最大点权独立集 ——HDU 1569 方格取数(2)
- HDU 1569 - 方格取数(2) 二分图最大点权独立集(构图最大流解)
- HDU:1569:方格取数(2)(最小割)
- HDU 1565 1569 方格取数(最大点权独立集)
- hdu 1569 方格取数(2) 最大权独立集
- HDU 1565 1569 方格取数 (最小割)
- hdu 1569 方格取数(2)--最大点权独立集-->最大流
- hdu 1565 方格取数(1)(最小割,最大点权独立集)
- hdu - 1565 方格取数(1) && 1569 方格取数(2) (最大点权独立集)
- hdu 1569 方格取数(2)【最大权独立集合-------最大流Edmond_Karp】
- hdu 1569 方格取数(2) 网络流--最大点权独立集
- hdu 1565 方格取数(1)/hdu 1569 方格取数(2)(最小割,黑白染色)
- 最小割的应用--方格取数问题(HDU 1565,HDU 1569)
- 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)
- hdu 1569 方格取数(2) 最大点权独立集
- HDU 1569 方格取数(2) (二分图的最大点权独立集)
- hdu 1569 方格取数(2) 最大点权独立集