传送门

模型

二分图最大独立集,转化为二分图最大匹配,从而用最大流解决。

实现

首先把棋盘黑白染色,使相邻格子颜色不同。

把所有可用的黑色格子看做二分图X集合中顶点,可用的白色格子看做Y集合顶点。

建立附加源S汇T,从S向X集合中每个顶点连接一条容量为1的有向边,从Y集合中每个顶点向T连接一条容量为1的有向边。

从每个可用的黑色格子向骑士一步能攻击到的可用的白色格子连接一条容量为无穷大的有向边。

求出网络最大流,要求的结果就是可用格子的数量减去最大流量。

分析

用网络流的方法解决棋盘上的问题,一般都要对棋盘黑白染色,使之成为一个二分图。放尽可能多的不能互相攻击的骑士,就是一个二分图最大独立集问题。有关二分图最大独立集问题,更多讨论见《最小割模型在信息学竞赛中的应用》作者胡伯涛。

该题规模比较大,需要用效率较高的网络最大流算法解决。(使用Dinic+当前弧优化)

——代码

  1. #include <queue>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <iostream>
  5. #define INF 1e9
  6. #define N 1000001
  7. #define min(x, y) ((x) < (y) ? (x) : (y))
  8.  
  9. int n, m, cnt, tot, sum, s, t;
  10. int map[][], head[N], to[N], val[N], next[N], dis[N], cur[N];
  11. int dx[] = {-, -, , , , , -, -},
  12. dy[] = {, , , , -, -, -, -};
  13.  
  14. inline int read()
  15. {
  16. int x = , f = ;
  17. char ch = getchar();
  18. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
  19. for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
  20. return x * f;
  21. }
  22.  
  23. inline void add2(int x, int y, int z)
  24. {
  25. to[cnt] = y;
  26. val[cnt] = z;
  27. next[cnt] = head[x];
  28. head[x] = cnt++;
  29. }
  30.  
  31. inline void add(int x, int y, int z)
  32. {
  33. add2(x, y, z);
  34. add2(y, x, );
  35. }
  36.  
  37. inline bool bfs()
  38. {
  39. int i, u, v;
  40. std::queue <int> q;
  41. memset(dis, -, sizeof(dis));
  42. q.push(s);
  43. dis[s] = ;
  44. while(!q.empty())
  45. {
  46. u = q.front(), q.pop();
  47. for(i = head[u]; i ^ -; i = next[i])
  48. {
  49. v = to[i];
  50. if(val[i] && dis[v] == -)
  51. {
  52. dis[v] = dis[u] + ;
  53. if(v == t) return ;
  54. q.push(v);
  55. }
  56. }
  57. }
  58. return ;
  59. }
  60.  
  61. inline int dfs(int u, int maxflow)
  62. {
  63. if(u == t) return maxflow;
  64. int v, d, ret = ;
  65. for(int &i = cur[u]; i ^ -; i = next[i])
  66. {
  67. v = to[i];
  68. if(val[i] && dis[v] == dis[u] + )
  69. {
  70. d = dfs(v, min(val[i], maxflow - ret));
  71. ret += d;
  72. val[i] -= d;
  73. val[i ^ ] += d;
  74. if(ret == maxflow) return ret;
  75. }
  76. }
  77. return ret;
  78. }
  79.  
  80. int main()
  81. {
  82. int i, j, k, x, y;
  83. n = read();
  84. m = read();
  85. s = , t = n * n + ;
  86. memset(head, -, sizeof(head));
  87. for(i = ; i <= m; i++)
  88. {
  89. x = read();
  90. y = read();
  91. map[x][y] = -;
  92. }
  93. for(i = ; i <= n; i++)
  94. for(j = ; j <= n; j++)
  95. if(!map[i][j])
  96. {
  97. map[i][j] = ++tot;
  98. if((i + j) & ) add(s, tot, );
  99. else add(tot, t, );
  100. }
  101. for(i = ; i <= n; i++)
  102. for(j = ; j <= n; j++)
  103. if(map[i][j] ^ - && (i + j) & )
  104. for(k = ; k < ; k++)
  105. {
  106. x = i + dx[k];
  107. y = j + dy[k];
  108. if(x >= && x <= n && y >= && y <= n && map[x][y] ^ -) add(map[i][j], map[x][y], INF);
  109. }
  110. while(bfs())
  111. {
  112. for(i = s; i <= t; i++) cur[i] = head[i];
  113. sum += dfs(s, INF);
  114. }
  115. printf("%d\n", tot - sum);
  116. return ;
  117. }

[luoguP3355] 骑士共存问题(二分图最大独立集)的更多相关文章

  1. 洛谷P3355 骑士共存问题 二分图_网络流

    Code: #include<cstdio> #include<cstring> #include<queue> #include<vector> #i ...

  2. 【Codevs1922】骑士共存问题(最小割,二分图最大独立集转最大匹配)

    题意: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入. 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个 ...

  3. 「CODVES 1922 」骑士共存问题(二分图的最大独立集|网络流)&dinic

    首先是题目链接  http://codevs.cn/problem/1922/ 结果发现题目没图(心情复杂 然后去网上扒了一张图 大概就是这样了. 如果把每个点和它可以攻击的点连一条边,那问题就变成了 ...

  4. Cogs 746. [网络流24题] 骑士共存(最大独立集)

    [网络流24题] 骑士共存 ★★☆ 输入文件:knight.in 输出文件:knight.out 简单对比 时间限制:1 s 内存限制:128 MB 骑士共存问题 «问题描述: 在一个n*n个方格的国 ...

  5. COGS746. [网络流24题] 骑士共存

    骑士共存问题«问题描述:在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘 上某些方格设置了障碍,骑士不得进入. «编程任务:对于给定的n*n个方格的国际象棋棋盘和障碍标志 ...

  6. 【刷题】LOJ 6226 「网络流 24 题」骑士共存问题

    题目描述 在一个 \(\text{n} \times \text{n}\) 个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入. 对于给定的 \(\t ...

  7. P3355 骑士共存问题

    P3355 骑士共存问题 题目描述 在一个 n*n (n <= 200)个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n ...

  8. BZOJ3175:[TJOI2013]攻击装置(二分图最大独立集)

    Description 给定一个01矩阵,其中你可以在0的位置放置攻击装置.每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2), ...

  9. [网络流24题] 骑士共存(cogs 746)

    骑士共存问题«问题描述:在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘 上某些方格设置了障碍,骑士不得进入. «编程任务:对于给定的n*n个方格的国际象棋棋盘和障碍标志 ...

随机推荐

  1. [dp uestc oj] G - 邱老师玩游戏

    G - 邱老师玩游戏 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submi ...

  2. codeforces Gym 100286J Javanese Cryptoanalysis (二染色)

    每一单词相邻两个字母,不能同时为元音或者辅音... 各种姿势都可以过:7个for,dp,黑白染色,dfs,并查集.... 最主要的思路就是相邻字母连边,把元音和辅音看成两个集合,那么有连边的两个字母一 ...

  3. 2018.4.28 基于java的聊天系统(带完善)

    Java聊天系统 1.Socket类 Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号. Socket(String ...

  4. centos7 python3 Saltstack配置

    Python安装完毕后,提示找不到ssl模块 pip is configured with locations that require TLS/SSL, however the ssl module ...

  5. java基础—static关键字

    一.static关键字

  6. 服务器上搭建flowvisor平台

    之前全是在virtualbox上的Ubuntu虚拟机上测试的ovs以及pox, 现在我们开始在服务器上开始了 两台服务器上的ovs均是1.4.6版本 遇到一个问题:之前装的ovs down了 然后什么 ...

  7. ios sinaweibo 客户端(三)

    这个页面要讲述的是用户的粉丝列表,下面是效果图: 可以看到这个视图明显也是一个tableview,在每一个cell中包含的有三个部分的内容:粉丝头像image,粉丝昵称label,我和粉丝之间的相互关 ...

  8. poj3335 Rotating Scoreboard

    题目描述: vjudge POJ 题解: 半平面交判核的存在性. 重点在于一个点的核也算核. 这样的话普通的求多边形的版本就要加一个特判. 就是把剩下的一个节点暴力带回所有直线重判,这时判叉积是否$\ ...

  9. 201621123080《JAVA程序设计》第八周学习总结

    作业08-集合 1. 本周学习总结 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 根据代码,首先在源数组里找到下标,若下标符合>=0 ...

  10. LeetCode935

    问题:935. 骑士拨号器 国际象棋中的骑士可以按下图所示进行移动:  .            这一次,我们将 “骑士” 放在电话拨号盘的任意数字键(如上图所示)上,接下来,骑士将会跳 N-1 步. ...