题意:nxn的棋盘 有m个坏点 求能在棋盘上放多少个马不会互相攻击

题解:这个题仔细想想居然和方格取数是一样的!!!

   每个马他能攻击到的地方的坐标 (x+y)奇偶性不一样 于是就黑白染色

   s->黑 白->t

   按条件连黑->白 跑最小割 = 最大流

   感性理解一下 就是先把所有的点都放上 得到最大的收益

   然后删掉一些点使得合法 删掉一个黑点 减去黑点的收益 和黑点相连的白点受到的束缚就减少了

   如果s和t点能联通的话 表示还有黑点和白点连通 问题就转化为了最小割

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int INF = 0x3f3f3f3f;
  4. int n, m, s, t, cnt, maxflow;
  5. int broke[205][205];
  6.  
  7. struct node {
  8. int to, nex, val;
  9. }E[400005];
  10. int head[40005];
  11. int cur[40005];
  12. int dx[] = {-1, -1, 1, 1, -2, -2, 2, 2};
  13. int dy[] = {2, -2, 2, -2, 1, -1, 1, -1};
  14.  
  15. void addedge(int x, int y, int va) {
  16. E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va;
  17. E[++cnt].to = x; E[cnt].nex = head[y]; head[y] = cnt; E[cnt].val = 0;
  18. }
  19.  
  20. int dep[40005];
  21. int inque[40005];
  22. bool bfs() {
  23. for(int i = 0; i <= t; i++) dep[i] = INF, inque[i] = 0, cur[i] = head[i];
  24. queue<int> que;
  25. dep[s] = 0; inque[s] = 1;
  26. que.push(s);
  27.  
  28. while(!que.empty()) {
  29. int u = que.front();
  30. que.pop();
  31. inque[u] = 0;
  32.  
  33. for(int i = head[u]; i; i = E[i].nex) {
  34. int v = E[i].to;
  35. if(E[i].val > 0 && dep[v] > dep[u] + 1) {
  36. dep[v] = dep[u] + 1;
  37. if(!inque[v]) {
  38. que.push(v);
  39. inque[v] = 1;
  40. }
  41. }
  42. }
  43. }
  44. if(dep[t] != INF) return true;
  45. return false;
  46. }
  47.  
  48. int vis;
  49. int dfs(int x, int flow) {
  50. if(x == t) {
  51. vis = 1;
  52. maxflow += flow;
  53. return flow;
  54. }
  55.  
  56. int used = 0;
  57. int rflow = 0;
  58. for(int i = cur[x]; i; i = E[i].nex) {
  59. cur[x] = i;
  60. int v = E[i].to;
  61. if(E[i].val > 0 && dep[v] == dep[x] + 1) {
  62. if(rflow = dfs(v, min(flow - used, E[i].val))) {
  63. used += rflow;
  64. E[i].val -= rflow;
  65. E[i ^ 1].val += rflow;
  66. if(used == flow) break;
  67. }
  68. }
  69. }
  70. return used;
  71. }
  72.  
  73. void dinic() {
  74. maxflow = 0;
  75. while(bfs()) {
  76. vis = 1;
  77. while(vis) {
  78. vis = 0;
  79. dfs(s, INF);
  80. }
  81. }
  82. }
  83.  
  84. int id(int x, int y) {
  85. return (x - 1) * n + y;
  86. }
  87.  
  88. bool check(int x, int y) {
  89. if(x >= 1 && x <= n && y >= 1 && y <= n) return true;
  90. return false;
  91. }
  92.  
  93. int main() {
  94. cnt = 1;
  95. scanf("%d%d", &n, &m);
  96. s = 0;
  97. t = n * n + 1;
  98.  
  99. for(int i = 1; i <= m; i++) {
  100. int x, y; scanf("%d%d", &x, &y);
  101. broke[x][y] = 1;
  102. }
  103. for(int i = 1; i <= n; i++) {
  104. for(int j = 1; j <= n; j++) {
  105. int ii = id(i, j);
  106. if(broke[i][j]) continue;
  107.  
  108. if((i + j) % 2 != 1) {
  109. addedge(s, ii, 1);
  110. for(int k = 0; k < 8; k++) {
  111. int ax = i + dx[k];
  112. int ay = j + dy[k];
  113. if(check(ax, ay) && !broke[ax][ay]) addedge(ii, id(ax, ay), INF);
  114. }
  115. } else addedge(ii, t, 1);
  116. }
  117. }
  118. dinic();
  119. printf("%d\n", n * n - m - maxflow);
  120. return 0;
  121. }

P3355 骑士共存问题 (最小割)的更多相关文章

  1. 洛谷.3355.骑士共存问题(最小割ISAP)

    题目链接 一个很暴力的想法:每个点拆点,向不能同时存在的连边 但是这样边太多了,而且会有很多重复.我不会说我还写了还没过样例 我们实际就是在做一个最大匹配.考虑原图,同在黄/红格里的骑士是互不攻击的, ...

  2. P3355 骑士共存问题

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

  3. P3355 骑士共存问题 二分建图 + 当前弧优化dinic

    P3355 骑士共存问题 题意: 也是一个棋盘,规则是“马”不能相互打到. 思路: 奇偶点分开,二分图建图,这道题要注意每个点可以跑八个方向,两边都可以跑,所以边 = 20 * n * n. 然后di ...

  4. 【Luogu】P3355骑士共存问题(最小割)

    题目链接 像题面那样把棋盘染成红黄点.发现骑士迈一步能到达的点的颜色一定是跟他所在的格子的颜色不同的.于是(woc哪来的于是?这个性质有这么明显吗?)从源点向所有红点连边,从所有黄点向汇点连边,红点向 ...

  5. 洛谷P3355 骑士共存问题(最小割)

    传送门 de了两个小时的bug愣是没发现错在哪里……没办法只好重打了一遍竟然1A……我有点想从这里跳下去了…… 和方格取数问题差不多,把格子按行数和列数之和的奇偶性分为黑的和白的,可以发现某种颜色一定 ...

  6. 洛谷P3355 骑士共存问题

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

  7. P3355 骑士共存问题 网络流

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

  8. 2018.08.02 洛谷P3355 骑士共存问题(最小割)

    传送门 这题让我联想到一道叫做方格取数问题的题,如果想使摆的更多,就要使不能摆的更少,因此根据骑士的限制条件建图,求出至少有多少骑士不能摆,减一减就行了. 代码: #include<bits/s ...

  9. 洛谷 P3355 骑士共存问题【最小割】

    同方格取数问题:https://www.cnblogs.com/lokiii/p/8430720.html 记得把障碍点去掉,不连边也不计入sum #include<iostream> # ...

随机推荐

  1. LeetCode解题Golang(1-10)

    前言 LeetCode题目个人答案(Golang版) 本篇预期记录 1-10 题, 持续更新 正文 1.两数之和(简单) https://leetcode-cn.com/problems/two-su ...

  2. Redis Cluster 集群节点信息 维护篇(二)

    集群信息文件: # cluster 集群内部信息对应文件,由集群自动维护. /data/soft/redis/6379data/nodes-6379.conf 集群信息查看: ./redis-trib ...

  3. Python绘制雷达图(俗称六芒星)

    原文链接:https://blog.csdn.net/Just_youHG/article/details/83904618 背景 <Python数据分析与挖掘实战> 案例2–航空公司客户 ...

  4. 记一次使用logmnr查找操作人流程

    经常遇到开发的需求,帮我查一下是谁修改了表里面的记录,是谁对表进行了DDL操作,此类问题可以使用logmnr解决 1.根据操作时间定位归档日志 SELECT name FROM V$ARCHIVED_ ...

  5. Windows+.Net Framework+svn+IIS在Jenkins上的自动化部署入门

    关于Jenkins的使用及安装,上一篇文章我已经介绍过了,Windows+.NetCore+git+IIS在Jenkins上的自动化部署入门.这篇主要是在jenkins如何安装SVN和MSBuild. ...

  6. 如何在windows开机画面里隐藏用户

    当开机的时候都会在欢迎屏幕中显示一个账户或者多个已经建立的账户,通常还会显示登录的用户名,我们可以通过修改注册表实现把某个用户隐藏,具体方法如下:http://hi.baidu.com/liminsu ...

  7. [Usaco2008 Mar]River Crossing渡河问题

    题目描述 Farmer John以及他的N(1 <= N <= 2,500)头奶牛打算过一条河,但他们所有的渡河工具,仅仅是一个木筏. 由于奶牛不会划船,在整个渡河过程中,FJ必须始终在木 ...

  8. 24V转5V稳压芯片,高效率的同步降压DC-DC变换器3A输出电流

    PW2330开发了一种高效率的同步降压DC-DC变换器3A输出电流.PW2330在4.5V到30V的宽输入电压范围内工作集成主开关和同步开关,具有非常低的RDS(ON)以最小化传导损失.PW2330采 ...

  9. linux编译模块,包含了头文件却还是报undifind警告

    在编写一个自己写的gadget驱动的时候遇到一个这样的问题,编译的时候报了个警告:WARNING: "usb_composite_register" [-/my_zero.ko] ...

  10. LoadRunner监控Centos和Ubuntu资源之服务器配置

    Centos 我用的版本是Centos6.8   首先更新源以及基础操作我就不说了,直接上步骤: Step 1 安装相关程序 执行命令:yum install inetd,这一步是为了安装rstatd ...