题目描述

在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘上某些方格设置了障碍,骑士不得进入

  

对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击

输入输出格式

输入格式:

第一行有 2 个正整数n 和 m (1<=n<=200, 0<=m<n2),分别表示棋盘的大小和障碍数。接下来的 m 行给出障碍的位置。每行 2 个正整数,表示障碍的方格坐标。

输出格式:

将计算出的共存骑士数输出

输入输出样例

输入样例#1: 复制

  1. 3 2
  2. 1 1
  3. 3 3
输出样例#1: 复制

  1. 5
最大流与最小割之间的转换
最多放多少骑士==最少拿走多少
观察图片不难发现:黄色的不能攻击黄色的,红色同理
那么不难想到二分图匹配
这样就转化成了二分图最小定点覆盖
而二分图最小顶点覆盖==二分图最大匹配。证明可以看[这里](http://www.cnblogs.com/jianglangcaijin/p/6035945.html)
从S向红色连边(权重为1),从红色向能攻击到的黄色连边(权重为INF),从黄色向T连边(权重为1)
 
  1. // luogu-judger-enable-o2
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<queue>
  5. #define AddEdge(x,y,z) add_edge(x,y,z),add_edge(y,x,0);
  6. using namespace std;
  7. const int MAXN=,INF=1e8+;
  8. inline char nc()
  9. {
  10. static char buf[MAXN],*p1=buf,*p2=buf;
  11. return p1==p2&&(p2=(p1=buf)+fread(buf,,MAXN,stdin),p1==p2)?EOF:*p1++;
  12. }
  13. inline int read()
  14. {
  15. char c=nc();int x=,f=;
  16. while(c<''||c>''){if(c=='-')f=-;c=nc();}
  17. while(c>=''&&c<=''){x=x*+c-'';c=nc();}
  18. return x*f;
  19. }
  20. int N,M,S,T;
  21. struct node
  22. {
  23. int u,v,flow,nxt;
  24. }edge[MAXN*];
  25. int head[MAXN],cur[MAXN],num=;
  26. inline void add_edge(int x,int y,int z)
  27. {
  28. edge[num].u=x;
  29. edge[num].v=y;
  30. edge[num].flow=z;
  31. edge[num].nxt=head[x];
  32. head[x]=num++;
  33. }
  34. int deep[MAXN];
  35. inline bool BFS()
  36. {
  37. memset(deep,,sizeof(deep));
  38. deep[S]=;
  39. queue<int>q;
  40. q.push(S);
  41. while(q.size()!=)
  42. {
  43. int p=q.front();
  44. q.pop();
  45. for(int i=head[p];i!=-;i=edge[i].nxt)
  46. if(!deep[edge[i].v]&&edge[i].flow)
  47. {
  48. deep[edge[i].v]=deep[p]+;q.push(edge[i].v);
  49. if(edge[i].v==T) return ;
  50. }
  51. }
  52. return deep[T];
  53. }
  54. int DFS(int now,int nowflow)
  55. {
  56. if(now==T||nowflow<=) return nowflow;
  57. int totflow=;
  58. for(int &i=cur[now];i!=-;i=edge[i].nxt)
  59. {
  60. if(deep[edge[i].v]==deep[now]+&&edge[i].flow)
  61. {
  62. int canflow=DFS(edge[i].v,min(nowflow,edge[i].flow));
  63. edge[i].flow-=canflow;edge[i^].flow+=canflow;
  64. totflow+=canflow;
  65. nowflow-=canflow;
  66. if(nowflow<=) break;
  67. }
  68. }
  69. return totflow;
  70. }
  71. int Dinic()
  72. {
  73. int ans=;
  74. while(BFS())
  75. {
  76. memcpy(cur,head,sizeof(head));
  77. ans+=DFS(S,INF);
  78. }
  79. return ans;
  80. }
  81. int a[][],c[][];
  82. int xx[]={,-,-,-,-,+,+,+,+};
  83. int yy[]={,-,-,+,+,+,+,-,-};
  84. int main()
  85. {
  86. #ifdef WIN32
  87. freopen("a.in","r",stdin);
  88. #else
  89. #endif
  90. memset(head,-,sizeof(head));
  91. N=read();M=read();S=;T=N*N+;
  92. for(int i=;i<=M;i++)
  93. {
  94. int x=read(),y=read();
  95. c[x][y]=;
  96. }
  97. for(int i=;i<=N;i++)
  98. for(int j=;j<=N;j++)
  99. a[i][j]=(i-)*N+j;
  100. for(int i=;i<=N;i++)
  101. for(int j=;j<=N;j++)
  102. {
  103. if(c[i][j]) continue;
  104. if((i+j)%)
  105. {
  106. AddEdge(S,a[i][j],);
  107. for(int k=;k<=;k++)
  108. {
  109. int wx=i+xx[k],wy=j+yy[k];
  110. if(wx>=&&wx<=N&&wy>=&&wy<=N)
  111. AddEdge(a[i][j],a[wx][wy],INF);
  112. }
  113. }
  114. else AddEdge(a[i][j],T,);
  115. }
  116. printf("%d",N*N-M-Dinic());
  117.  
  118. return ;
  119. }
 
  1.  

洛谷P3355 骑士共存问题的更多相关文章

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

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

  2. 洛谷 [P3355] 骑士共存问题

    二分图求最大独立点集 本问题在二分图中已处理过,此处用dinic写了一遍 #include <iostream> #include <cstdio> #include < ...

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

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

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

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

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

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

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

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

  7. P3355 骑士共存问题

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

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

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

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

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

随机推荐

  1. ajax异步刷新

    前台js <script type="text/javascript"> function getLands() { $.ajax({ url:"httpse ...

  2. nj10---文件读取

    介绍:fs模块是文件操作的封装,它提供了文件的读取,写入,更名,删除,遍历目录,链接POSIX文件系统操作.与其他模块不同的是,fs模块中所有的操作都提供了异步和同步两个版本,例如读取文件内容函数异步 ...

  3. Tuples are immutable

    A tuple is a sequence of values. The values can be any type, and they are indexed by integers, so in ...

  4. metasploit.meterpreter学习笔记(博主推荐)

    Metasploit学习笔记(博主推荐) 继续上面的博客 metasploit.meterpreter的基本使用: 首先来获取当前系统(即xp)下的正在运行的一些进程 获得进程之后,我们通过migra ...

  5. 976 C. Nested Segments

    You are given a sequence a1, a2, ..., an of one-dimensional segments numbered 1 through n. Your task ...

  6. [BJWC2012]冻结 分层图最短路

    昨晚飞行路线之后,这道题就应该能一眼切了 题目当然也不难,跑一遍分层图最短路即可 Code: #include<cstring> #include<algorithm> #in ...

  7. Windows下使用VS的ADO访问MySQL

    数据库的访问的一种方式就是:CS结构.即使用TCP/UDP协议进行远程访问,而数据库对于服务端的软件是本地访问!这种管理方式比较常见. 这里主要叙述Windows访问本地数据库的方法. 需要了解几个概 ...

  8. 前端之CSS选择器

    基本选择器 元素选择器 p {color: "red";} ID选择器 #i1 { background-color: red; } 类选择器 .c1 { font-size: 1 ...

  9. [NOIP2014普及组]子矩阵

    题目:洛谷P2258.Vijos P1914.codevs 3904. 题目大意:给你一个矩阵,要你找一个r行c列的子矩阵,求最小分值(子矩阵和分值的定义见原题). 解题思路:n和m比较小,考虑暴力. ...

  10. Linux学习之socket编程(一)

    socket编程 socket的概念: 在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程,“IP地址+端口号”就称为socket. 在TCP协议中,建立连接的两个进 ...