题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1569
题解:
因为这个数据比较大,所以用动态规划会超时。
将图转换成黑白棋盘问题,i + j 为奇数的与s节点相连,边的权值为棋盘上对应位置的值,其他的与t节点相连,
边的权值为棋盘上对应位置的值,然后让棋盘上相邻之间的节点用边相连,边的权值为INF。这样问题就转换为
了最大点权独立集问题。
定理:
1、最大点权独立集 = sum - 最小点权覆盖集。
2、最小点权覆盖集 = 最小割 = 最大流
dinic实现:
#include <iostream> #include <cstdio> #include <queue> #include <cstring> #include <algorithm> using namespace std; const int maxn = 2550; const int inf = 0x7fffffff; struct node { int v,cost; int next; }edge[8*maxn]; int map[55][55]; int head[maxn],dis[maxn],id; int source,sink,res; int n,m; void add_edge(int u,int v,int cost) { edge[id].v = v;edge[id].cost = cost;edge[id].next = head[u];head[u] = id++; edge[id].v = u;edge[id].cost = 0; edge[id].next = head[v];head[v] = id++; } void build() { id = source = 0;sink = n*m+5; memset(head,-1,sizeof(head)); int i,j,t; for( i = 1; i <= n; i++) { for( j = 1; j <= m; j++) { t = (i-1)*m+j+1; if((i+j)&1) { add_edge(source,t,map[i][j]); if( i > 1) add_edge(t,t-m,inf); if( i < n ) add_edge(t,t+m,inf); if( j > 1) add_edge(t,t-1,inf); if( j < m ) add_edge(t,t+1,inf); } else add_edge(t,sink,map[i][j]); } } } bool bfs() { memset(dis,-1,sizeof(dis)); queue<int>que; dis[source] = 0; que.push(source); while( !que.empty()) { int u = que.front(); que.pop(); for( id = head[u] ; id != -1; id = edge[id].next) { int v = edge[id].v; if( edge[id].cost > 0 && dis[v] == -1) { dis[v] = dis[u] + 1; que.push(v); } } } return dis[sink] != -1; } int dinic(int u,int flow) { if( u == sink)return flow; int tmp = flow; for(int id = head[u] ; id != -1 ; id = edge[id].next) { int v = edge[id].v; if( edge[id].cost > 0 && dis[v] == dis[u] + 1) { int c = dinic(v,edge[id].cost < tmp ? edge[id].cost : tmp); tmp -= c; edge[id].cost -= c; edge[id^1].cost += c; if( tmp == 0)break; } } return flow - tmp; } int get_max_flow() { int max_flow = 0; while( bfs() ) max_flow += dinic(source,res); return max_flow; } int main() { int i,j; while( scanf("%d%d",&n,&m) != EOF) { res = 0; for( i = 1; i <= n; i++) for( j = 1; j <= m; j++) { scanf("%d",&map[i][j]); res += map[i][j]; } build(); printf("%d\n",res-get_max_flow()); } return 0; }