传送门

模型

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

实现

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

把所有可用的黑色格子看做二分图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. [VC]ocx控件怎么屏蔽backspace的后退键

    <script Language=javascript> function   document.onkeydown()   {   if(window.event.keyCode   = ...

  2. UVA11090 Going in Cycle (二分+判负环)

    二分法+spfa判负环.如果存在一个环sum(wi)<k*x,i=0,1,2...,k,那么每条边减去x以后会形成负环.因此可用spfa来判负环. 一般spfa判负环dfs最快,用stack次之 ...

  3. XManager 远程连接Netbackup图形用户界面

    XManager远程连接Netbackup图形用户界面   目标: 在自己的Windows桌面打开Linux的Netbackup图形用户界面 工具: Windows: Xmanager,Xshell, ...

  4. PhoneGap+JQuery Mobile移动应用开发学习笔记

    最近一直在学习使用PhoneGap+JQuery Mobile的开发框架开发Android应用,抛开这个框架的运行效率不说,暂且将使用中遇到的问题进行一下整理. 1.JS文件引用顺序 也许在进行web ...

  5. Bootstrap 页面标题(Page Header)

    Bootstrap页面标题(PageHeader)是个不错功能,它会网页的标题的四周添加适当的间距,当一个网页中有多个标题并且每个标题之间需要添加一定适当的间距,使用页面标题是非常有用的.如果需要使用 ...

  6. 八皇后问题(DFS)

    题目描述: 要在国际象棋棋盘中放八个皇后,使任意两个皇后都不能互相吃,皇后能吃同一行.同一列,同一对角线上(两个方向的对角线)的任意棋子.现在给一个整数n(n<=92),输出前n种的摆法. 输入 ...

  7. poj3525 Most Distant Point from the Sea

    题目描述: vjudge POJ 题解: 二分答案+半平面交. 半径范围在0到5000之间二分,每次取$mid$然后平移所有直线,判断半平面交面积是否为零. 我的eps值取的是$10^{-12}$,3 ...

  8. Linux - NodeJS安装

    1> 去NodeJS官网 https://nodejs.org/en/ 或 中文网 http://nodejs.cn/download/ 拷贝相应版本的安装文件,如下图: 2> 执行 wg ...

  9. jQuery plugin : bgStretcher 背景图片切换效果插件

    转自:http://blog.dvxj.com/pandola/jQuery_bgStretcher.html bgStretcher 2011 (Background Stretcher)是一个jQ ...

  10. PHP获取文件夹内所有文件包括子目录文件的名称或路径

    /* * new getFile($_dir[,$_emptyDir,$_fileType]); * @parma $_dir 是目录名称 * @parma $_emptyDir 是否获取空文件夹,选 ...