hdu 1569 方格取数(2)
来源:互联网 发布:banner请求网络图片 编辑:程序博客网 时间:2024/05/16 01:44
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1569
题目思路:
- 因为这个数据比较大,所以用动态规划会超时。
- 将图转换成黑白棋盘问题,i + j 为奇数的与s节点相连,边的权值为棋盘上对应位置的值,其他的与t节点相连,边的权值为棋盘上对应位置的值,然后让棋盘上相邻之间的节点用边相连,边的权值为INF。这样问题就转换为了最大点权独立集问题。
- 定理:
- 1、最大点权独立集 = sum - 最小点权覆盖集。
- 2、最小点权覆盖集 = 最小割 = 最大流
方格取数(2)
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3101 Accepted Submission(s): 944
Problem Description
给你一个m*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
Input
包括多个测试实例,每个测试实例包括2整数m,n和m*n个非负数(m<=50,n<=50)
Output
对于每个测试实例,输出可能取得的最大的和
Sample Input
3 375 15 21 75 15 28 34 70 5
Sample Output
188
代码:
/*定理:1、最大点权独立集 = sum - 最小点权覆盖集。2、最小点权覆盖集 = 最小割 = 最大流实现:dinic算法*/#include <iostream>#include<string.h>#include<stdio.h>using namespace std;const int nMax = 2505;const int INF = 0x7fffffff;int queue[nMax];//建立层次图时使用到的队列int dis[nMax];//各节点在层次图中对应的层次数struct Edge //邻接表,包括:边的起点、边的权值、起点相同的下一条边{ int v, w, next; Edge() {} Edge(int v, int w, int next):v(v), w(w), next(next) {}} adj[8 * nMax];int V[nMax];//V[u]表示起点为u的第一条边,与Edge结合使用,从而实现邻接表的效果int cnt;int s, t;int min(int a, int b){ return a < b ? a : b;}void add(int u, int v, int w)//向邻接表中添加 u - > v 结构{ adj[cnt] = Edge(v, w, V[u]); V[u] = cnt ++; adj[cnt] = Edge(u, 0, V[v]); V[v] = cnt ++;}int bfs()//建层次图{ int front, rear; int v; memset(dis, 0, sizeof(dis)); front = rear = 0; dis[s] = 1; queue[front ++] = s; while(rear < front) { int u = queue[rear ++]; for(int i = V[u]; i != -1; i = adj[i].next)//与u相连的边 if(adj[i].w && dis[v = adj[i].v] == 0)//可通行并且 v 之间没有被访问过 { dis[v] = dis[u] + 1; if(v == t) return 1; queue[front ++] = v; } } return 0;}int dfs(int u, int limit = INF)//返回从u出发到t,增广路经的最小边{ if(u == t) return limit; int count = 0; for(int i = V[u]; i != -1; i = adj[i].next)//与u 相连的边 { int v = adj[i].v; if((dis[v] == dis[u] + 1) && adj[i].w)//根据层次的关系,找到的路径就为最短路径 { int z = dfs(v, min(limit - count, adj[i].w)); if(z > 0)//增广路经的最小边不为0,即v到t可通行 { count += z; adj[i].w -= z; adj[i ^ 1].w += z;//改为adj[i + 1] += z , 会超时! } else dis[v] = -1;//效果等同于删除与v相关的所有边 } } return count;}int dinic(){ int ans = 0; while(bfs())//直到搜索不到增广路经为止 ans += dfs(s); return ans;}void init(){ cnt = 0; memset(V, -1, sizeof(V));}int main(){ int m, n; int sum; while(scanf("%d %d", &m, &n) != EOF) { init(); int x; sum = 0; s = 0; t = m * n + 1; for(int i = 1; i <= m; ++ i) for(int j = 1; j <= n; ++ j) { scanf("%d", &x); sum += x; if((i + j) & 1) { add(s, (i - 1) * n + j, x); //上 if(i > 1) add((i - 1) * n + j, (i - 2) * n + j, INF); //下 if(i < m) add((i - 1) * n + j, i * n + j, INF); //左 if(j > 1) add((i - 1) * n + j, (i -1) * n + j - 1, INF); //右 if(j < n) add((i - 1) * n + j, (i - 1) * n + j + 1, INF); } else add((i - 1) * n + j, t, x); } printf("%d\n",sum - dinic()); } return 0;}
- hdu 1569 方格取数(2)
- hdu 1569 方格取数(2)
- HDU 1569 方格取数(2)
- hdu 1569 方格取数(2)
- HDU 1569 方格取数(2)
- hdu 1569 方格取数(2)
- HDU 1569 方格取数(2)
- 方格取数(2) HDU
- hdu 1565 方格取数(1) and hdu 1569 方格取数(2)
- hdu 1565 方格取数(1)/hdu 1569 方格取数(2)(最小割,黑白染色)
- hdu 1569 方格取数(2)//最小割
- hdu 1569 方格取数(2) (最大流最小割)
- hdu 1569 方格取数(2) 最大权独立集
- hdu(1569)方格取数(2)(dinic算法)
- HDU 1569——方格取数(2) 【不用vector】
- 【网络流】hdu 1569 方格取数(2)
- 【网络流】 hdu 1569 方格取数(2)
- 【网络流】 HDU 1569 方格取数(2)
- html5实例解析:开发web app的过程(离线存储)
- git status简单用法
- Wince设置/删除/查询环境变量
- A*搜索算法随想
- sql*plus 学习
- hdu 1569 方格取数(2)
- git 官方简介
- 从零开始at91sam9263的linux编程----内核编译
- Oracle current high CPU load SQL
- ECMall模块开发2
- myeclipse工程下的js文件中文乱码问题
- forever: 让nodejs应用后台执行
- Jrebel的使用
- Android基础面试题