UVALive 6525 Attacking rooks 二分匹配 经典题
option=com_onlinejudge&Itemid=8&page=show_problem&problem=4536">点击打开链接
题意:
给定n*n的棋盘,
能够在'.'上摆 象棋中的车(X是墙壁)
使得随意两个车都不能互相攻击到
问:最多能摆多少个车。
思路:
二分匹配
1、若没有X。那么做法就是 X点集为行,Y点集为列,对于图上的每一个点所在的行和列(x,y) 建一条边 x->y
2、有了X,那么对于每一个点所在的上方能接触到的X必须各不同样。所以给每一个X标号,第一个X标记成n+1
3、这样X点集就是行(1-n) 和 n+1-siz (siz是X的个数)
4、对于每一个点,上方能接触到的近期的X作为列,右方能接触到的近期的Y作为行,建一条边 X->Y
而处理每一个点上方能接触到的近期的X就是一个dp。右方也是相同处理。
然后跑个二分匹配就好。
- <pre name="code" class="cpp">#pragma comment(linker, "/STACK:1024000000,1024000000")
- #include<bits/stdc++.h>
- template <class T>
- inline bool rd(T &ret) {
- char c; int sgn;
- if(c=getchar(),c==EOF) return 0;
- while(c!='-'&&(c<'0'||c>'9')) c=getchar();
- sgn=(c=='-')?-1:1;
- ret=(c=='-')?0:(c-'0');
- while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
- ret*=sgn;
- return 1;
- }
- template <class T>
- inline void pt(T x) {
- if (x <0) {
- putchar('-');
- x = -x;
- }
- if(x>9) pt(x/10);
- putchar(x%10+'0');
- }
- using namespace std;
- const int N = 10105;
- struct Edge{
- int to, nex;
- }edge[N*2];
- int head[N], edgenum;
- void init(){memset(head, -1, sizeof head); edgenum = 0;}
- void add(int u, int v){
- Edge E = {v, head[u]};
- edge[edgenum] = E;
- head[u] = edgenum++;
- }
- int lef[N], pn;
- int tim, T[N];
- bool match(int x){
- for(int i=head[x]; ~i; i=edge[i].nex)
- {
- int v = edge[i].to;
- if(T[v] != tim)
- {
- T[v] = tim;
- if(lef[v] == -1 || match( lef[v] )) //match(lef[v]) : 原本连接v的X集点 lef[v] 能不能和别人连。假设能 则v这个点就空出来和x连
- {
- lef[v] = x;
- return true;
- }
- }
- }
- return false;
- }
- int solve(){
- int ans = 0;
- memset(lef, -1, sizeof(lef));
- for(int i = 1; i<= pn; i++)//X集匹配。X集点标号从 1-pn 匹配边是G[左点].size()
- {
- tim++;
- if( match( i ) ) ans++;
- }
- return ans;
- }
- int n, siz, s[105][105], l[105][105], mp[105][105];
- char str[105];
- void input(){
- siz = n;
- for(int i = 1; i <= n; i++)
- {
- scanf("%s", str+1);
- for(int j = 1; j <= n; j++){
- if(str[j] == 'X')
- mp[i][j] = ++siz;
- else
- mp[i][j] = 0;
- }
- }
- }
- void build(){
- for(int i = 1; i <= n; i++)
- s[0][i] = i;
- for(int i = 1; i <= n; i++)
- for(int j = 1; j <= n; j++)
- if(mp[i][j])
- s[i][j] = mp[i][j];
- else
- s[i][j] = s[i-1][j];
- for(int i = 1; i <= n; i++)
- l[i][n+1] = i;
- for(int i = n; i; i--)
- {
- for(int j = 1; j <= n; j++)
- if(mp[j][i])
- l[j][i] = mp[j][i];
- else
- l[j][i] = l[j][i+1];
- }
- init();
- pn = siz;
- for(int i = 1; i <= n; i++)
- for(int j = 1; j <= n; j++)
- if(mp[i][j] == 0)
- add(l[i][j+1], s[i-1][j]);
- }
- int main(){
- tim = 1; memset(T, 0, sizeof T);
- while(cin>>n){
- input();
- build();
- cout<<solve()<<endl;
- }
- return 0;
- }
- /*
- 5
- X....
- X....
- ..X..
- .X...
- ....X
- 3
- .X.
- XXX
- XXX
- 3
- .X.
- X.X
- XXX
- 3
- .X.
- X.X
- X.X
- 3
- .X.
- X.X
- .X.
- 3
- XXX
- XXX
- XXX
- 15
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXX
- */
UVALive 6525 Attacking rooks 二分匹配 经典题的更多相关文章
- UVaLive 6525 Attacking rooks (二分图最大匹配)
题意:给定一个 n * n的图,X是卒, . 是空位置,让你放尽量多的车,使得他们不互相攻击. 析:把每行连续的 . 看成X集体的一个点,同理也是这样,然后求一个最大匹配即可. 代码如下: #prag ...
- ZOJ 1654 二分匹配基础题
题意: 给你一副图, 有草地(*),空地(o)和墙(#),空地上可以放机器人, 机器人向上下左右4个方向开枪(枪不能穿墙),问你在所有机器人都不相互攻击的情况下能放的最多的机器人数. 思路:这是一类经 ...
- HNU13028Attacking rooks (二分匹配,一行变多行,一列变多列)
Attacking rooks Time Limit: 20000ms, Special Time Limit:50000ms, Memory Limit:65536KB Total submit u ...
- POJ 1469 ZOJ1140 二分匹配裸题
很裸,左点阵n,右点阵m 问最大匹配是否为n #include <cstdio> #include <cstring> #include <vector> usin ...
- COURSES 赤裸裸的二分匹配大水题
COURSES 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include ...
- UVA5874 Social Holidaying 二分匹配
二分匹配简单题,看懂题意,建图比较重要. #include<stdio.h> #include<string.h> #define maxn 1100 int map[maxn ...
- hdu 1068 Girls and Boys (二分匹配)
Girls and Boys Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- poj2239 poj1274【二分匹配】
题意: 就是尽可能的选多的课 思路: 把课程和上课的时间看作二分图 跑一跑二分匹配就好了 #include<iostream> #include<cstdio> #includ ...
- HDU 3861 The King’s Problem(tarjan缩点+最小路径覆盖:sig-最大二分匹配数,经典题)
The King’s Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
随机推荐
- Remoting 的“传递的引用”理解
WCf是集大成者,具有其他微软的很多技术,其中分布式上很多借助于Remoting,所以研究一下Remoting有助于理解WCF 提到Remoting就不得不涉及到MarshalByRefObject这 ...
- __dopostback的用法 . 编辑
在.NET中,所有的服务器控件提交到服务器的时候,都会调用__doPostBack这个函数,所以灵活运用这个函数对于我们的帮助还是很大的. 比如,在我们写程序的时候经常会需要动态的生成一些控件,最简单 ...
- jQuery 小知识点(插件)
1.jQuery插件小知识点: 估计很多人都没弄明白下面的东西,特从网络上搜索了下面的知识,自己以后用起来也比较方便: $.fn是指jquery的命名空间,加上fn上的方法及属性,会对jquery实例 ...
- IMAGE_SECTION_HEADER
typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union { DWORD PhysicalAdd ...
- Flume笔记--source端监听目录,sink端上传到HDFS
官方文档参数解释:http://flume.apache.org/FlumeUserGuide.html#hdfs-sink 需要注意:文件格式,fileType=DataStream 默认为Sequ ...
- ubuntu下怎么显示右上角的小键盘
Ubuntu右上角小键盘不见了解决方法: ibus输入法的图标经常消失,输入中文时很不方便,重启一下ibus! 按Ctrl+ALT+T 快捷键打开终端, 输入: 1.killall ibu ...
- hdu 2992 Hotel booking
http://acm.hdu.edu.cn/showproblem.php?pid=2992 #include <cstdio> #include <cstring> #inc ...
- rsync同步目录及同步文件
最简单的只读同步工作. 一,服务端的配置 1,安装rsync(阿里云默认已有此程序) 略 2,生成文件rsyncd.conf,内容如下: #secrets file = /etc/rsyncd.sec ...
- JVM虚拟机栈和本地方法栈溢出测试
弄JAVA,那JVM,JAVA语法,JDK库,JAVAEE,流行框架是一个都不能少,才可以有全局感的. JVM高级特性这书,看得差不多了.慢慢实践. /** * * *VM Args: -Xms20m ...
- 51单片机C语言学习笔记7:关于.c文件和.h文件
1)h文件作用 1 方便开发:包含一些文件需要的共同的常量,结构,类型定义,函数,变量申明: 2 提供接口:对一个软件包来说可以提供一个给外界的接口(例如: stdio.h). 2)h文件里应该有什么 ...