http://acm.hdu.edu.cn/showproblem.php?pid=1565

题意:中文。

思路:一个棋盘,要使得相邻的点不能同时选,问最大和是多少,这个问题就是最大点权独立集。

可以转化为所有的点权 - 最小点权覆盖集(最小割) = 最大点权独立集。

转载两个的定义:这里

覆盖集(vertex covering set,VCS)是无向图的一个点集,使得该图中所有边都至少有一个端点在该集合内。形式化的定义是点覆盖集为G'VV∈(,)uvE∀∈,满足对于,都有 或成立,即,'uV∈'vV∈'uV∈'vV∈至少一个成立。形象地说是若干个点“覆盖”住了 与它们邻接的边,这些边恰好组成了原边集。

点独立集(vertex independent set,VIS)是无向图的一个点集,使得任两个在该集合中的点在原图中都不相邻。或者说是导出子图为零图(没有边)的点集。形式化的定义是点独立集为,满足对于,都有G'VV∈,'uvV∀∈(,)uvE∉成立。点独立集还有一种等价的定义:点独立集为,满足对于,都有'VV∈'uV∈'vV∈(,)uvE∀∈与不同时成立。

从覆盖集的定义可以看出,求覆盖集就是求最小割(最大流),这个最小点权覆盖集不是S集合就是T集合,最大权独立集就是最小点权覆盖集的补集。

因此把棋盘通过黑白染色:

设一种颜色和S相连(容量为点权),然后用这种颜色去连接相邻另一种颜色(容量为INF),另一种颜色和T相连(容量为点权)。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <queue>
  4. using namespace std;
  5. #define N 510
  6. #define INF 0x3f3f3f3f
  7. typedef long long LL;
  8. struct Edge {
  9. int v, nxt, cap;
  10. Edge () {}
  11. Edge (int v, int nxt, int cap) : v(v), nxt(nxt), cap(cap) {}
  12. } edge[N*N];
  13. int head[N], tot, dis[N], cur[N], pre[N], gap[N], n, mp[][], dx[] = {, , , -}, dy[] = {, -, , };
  14.  
  15. bool check(int x, int y) {
  16. if( <= x && x <= n && <= y && y <= n) return true;
  17. return false;
  18. }
  19.  
  20. void Add(int u, int v, int cap) {
  21. edge[tot] = Edge(v, head[u], cap); head[u] = tot++;
  22. edge[tot] = Edge(u, head[v], ); head[v] = tot++;
  23. }
  24.  
  25. int BFS(int S, int T) {
  26. queue<int> que; que.push(T);
  27. memset(dis, INF, sizeof(dis));
  28. memset(gap, , sizeof(gap));
  29. gap[]++; dis[T] = ;
  30. while(!que.empty()) {
  31. int u = que.front(); que.pop();
  32. for(int i = head[u]; ~i; i = edge[i].nxt) {
  33. int v = edge[i].v;
  34. if(dis[v] == INF) {
  35. dis[v] = dis[u] + ;
  36. gap[dis[v]]++;
  37. que.push(v);
  38. }
  39. }
  40. }
  41. }
  42.  
  43. LL ISAP(int S, int T, int n) {
  44. BFS(S, T);
  45. memcpy(cur, head, sizeof(cur));
  46. int u = pre[S] = S, i, index, flow; LL ans = ;
  47. while(dis[S] < n) {
  48. if(u == T) {
  49. flow = INF, index = S; // index = S !!!
  50. for(i = S; i != T; i = edge[cur[i]].v)
  51. if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
  52. for(i = S; i != T; i = edge[cur[i]].v)
  53. edge[cur[i]].cap -= flow, edge[cur[i]^].cap += flow;
  54. ans += flow, u = index;
  55. }
  56. for(i = cur[u]; ~i; i = edge[i].nxt)
  57. if(edge[i].cap > && dis[edge[i].v] == dis[u] - ) break;
  58. if(~i) {
  59. pre[edge[i].v] = u; cur[u] = i; u = edge[i].v;
  60. } else {
  61. if(--gap[dis[u]] == ) break;
  62. int md = n;
  63. for(i = head[u]; ~i; i = edge[i].nxt)
  64. if(md > dis[edge[i].v] && edge[i].cap > ) md = dis[edge[i].v], cur[u] = i;
  65. gap[dis[u] = md + ]++;
  66. u = pre[u];
  67. }
  68. }
  69. return ans;
  70. }
  71.  
  72. int main() {
  73. while(~scanf("%d", &n)) {
  74. memset(head, -, sizeof(head)); tot = ;
  75. int S = , T = n * n + ; LL sum = ;
  76. for(int i = ; i <= n; i++) for(int j = ; j <= n; j++) scanf("%d", &mp[i][j]), sum += mp[i][j];
  77. for(int i = ; i <= n; i++) {
  78. for(int j = ; j <= n; j++) {
  79. if((i + j) % ) Add(S, (i - ) * n + j, mp[i][j]);
  80. else Add((i - ) * n + j, T, mp[i][j]);
  81. for(int k = ; k < ; k++) {
  82. int nx = i + dx[k], ny = j + dy[k];
  83. if(check(nx, ny) && (i + j) % ) Add((i - ) * n + j, (nx - ) * n + ny, INF);
  84. }
  85. }
  86. }
  87. printf("%lld\n", sum - ISAP(S, T, T + ));
  88. }
  89. return ;
  90. }

点覆盖集

vertex covering set

VCS

)是无向图

的一个点集,使得该图中所有边都至少

有一个端点在该集合内。形式化的定义是点覆盖集为

G

'

V

V

(

,

)

u

v

E

,满足对于

,都有

成立,即

'

u

V

'

v

V

'

u

V

'

v

V

至少一个成立。形象地说是若干个点“覆盖”住了

与它们邻接的边,这些边恰好组成了原边集。

点独立集

vertex independent set

VIS

)是无向图

的一个点集,使得任两个在该集合中

的点在原图中都不相邻。或者说是导出子图为零图(没有边)的点集。形式化的定义是点独

立集为

,满足对于

,都有

G

'

V

V

,

'

u

v

V

(

,

)

u

v

E

成立。点独立集还有一种等价的定义:

点独立集为

,满足对于

,都有

'

V

V

'

u

V

'

v

V

(

,

)

u

v

E

不同时成立。

HDU 1565:方格取数(1)(最大点权独立集)***的更多相关文章

  1. HDU 1569 - 方格取数(2) - [最大点权独立集与最小点权覆盖集]

    嗯,这是关于最大点权独立集与最小点权覆盖集的姿势,很简单对吧,然后开始看题. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1569 Time Limi ...

  2. HDU 1565 1569 方格取数(最大点权独立集)

    HDU 1565 1569 方格取数(最大点权独立集) 题目链接 题意:中文题 思路:最大点权独立集 = 总权值 - 最小割 = 总权值 - 最大流 那么原图周围不能连边,那么就能够分成黑白棋盘.源点 ...

  3. hdu - 1565 方格取数(1) && 1569 方格取数(2) (最大点权独立集)

    http://acm.hdu.edu.cn/showproblem.php?pid=1565 两道题只是数据范围不同,都是求的最大点权独立集. 我们可以把下标之和为奇数的分成一个集合,把下标之和为偶数 ...

  4. hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)

    /** 转自:http://blog.csdn.net/u011498819/article/details/20772147 题目:hdu1569 方格取数(2) 链接:https://vjudge ...

  5. TZOJ 3665 方格取数(2)(最大点权独立集)

    描述 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大. 输入 包括多个测试实例 ...

  6. hdu1569 方格取数 求最大点权独立集

    题意:一个方格n*m,取出一些点,要求两两不相邻,求最大和.思路:建图,相邻的点有一条边,则建立了一个二分图,求最大点权独立集(所取点两两无公共边,权值和最大),问题转化为求总权和-最小点权覆盖集(点 ...

  7. 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)

      HDU 1565 方格取数(1) 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的 ...

  8. HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]

    题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...

  9. HDU 1565 方格取数(1) 轮廓线dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others) ...

  10. HDU 1565 方格取数(1)(最大点权独立集)

    http://acm.hdu.edu.cn/showproblem.php?pid=1565 题意: 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格 ...

随机推荐

  1. 区别JS和DOM对象

    <div> <button id="bt" onclick="ChangeColor()">Clike To Change Color& ...

  2. 【msdn wpf forum翻译】TextBox中文本 中对齐 的方法

    原文:[msdn wpf forum翻译]TextBox中文本 中对齐 的方法 原文链接:http://social.msdn.microsoft.com/Forums/en-US/wpf/threa ...

  3. C# GetFiles

    var path = AppDomain.CurrentDomain.BaseDirectory + "Images\\Rooms\\"; // string[] patterns ...

  4. Interactive Data Display如何显示菜单?

    貌似直接跟其它控件一样添加菜单就行了. 不过这个版本已经取消了默认菜单,所有的菜单功能都得自己去实现.

  5. 修复VirtualBox "This kernel requires the following features not present on the CPU: pae Unable to boot – please use a kernel appropriate for your CPU"(安装深度Linux的时候就需要)

    异常处理汇总-开发工具  http://www.cnblogs.com/dunitian/p/4522988.html 修复VirtualBox "This kernel requires ...

  6. Android零基础入门第77节:Activity任务栈和启动模式

    通过前面的学习,Activity的基本使用都已掌握,接下来一起来学习更高级的一些内容. Android采用任务栈(Task)的方式来管理Activity的实例.当启动一个应用时,Android就会为之 ...

  7. enum 枚举一般用法 dotnet

    public enum Demo { [Description("Moning描述")] Moning = , [Description("Afternoon描述&quo ...

  8. Delphi中,indy控件实现收发邮件的几点学习记录( 可以考虑加入多线程,用多个邮箱做一个邮箱群发器) 转

    关于用Delphi中的Indy控件实现收发邮件的几点学习记录             这几天心里颇不宁静,不是因为项目延期,而是因为自己几个月前做的邮件发送程序至今无任何进展,虽然一向谦虚的人在网上发 ...

  9. Google地图下载工具代码

    // // Google Map Tiles Downloader in C# by coolypf // No rights reserved, neither warranty nor guara ...

  10. 客服端JavaScript线程模型

    JavaScript语言核心并不包含任何线程机制,并且客服端JavaScript传统上没有定义任何线程机制.HTML5定义了一种作为后台线程的“WebWorker",但是客服端JavaScr ...