题目链接:

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 二分匹配 经典题的更多相关文章

  1. UVaLive 6525 Attacking rooks (二分图最大匹配)

    题意:给定一个 n * n的图,X是卒, . 是空位置,让你放尽量多的车,使得他们不互相攻击. 析:把每行连续的 . 看成X集体的一个点,同理也是这样,然后求一个最大匹配即可. 代码如下: #prag ...

  2. ZOJ 1654 二分匹配基础题

    题意: 给你一副图, 有草地(*),空地(o)和墙(#),空地上可以放机器人, 机器人向上下左右4个方向开枪(枪不能穿墙),问你在所有机器人都不相互攻击的情况下能放的最多的机器人数. 思路:这是一类经 ...

  3. HNU13028Attacking rooks (二分匹配,一行变多行,一列变多列)

    Attacking rooks Time Limit: 20000ms, Special Time Limit:50000ms, Memory Limit:65536KB Total submit u ...

  4. POJ 1469 ZOJ1140 二分匹配裸题

    很裸,左点阵n,右点阵m 问最大匹配是否为n #include <cstdio> #include <cstring> #include <vector> usin ...

  5. COURSES 赤裸裸的二分匹配大水题

    COURSES 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include ...

  6. UVA5874 Social Holidaying 二分匹配

    二分匹配简单题,看懂题意,建图比较重要. #include<stdio.h> #include<string.h> #define maxn 1100 int map[maxn ...

  7. hdu 1068 Girls and Boys (二分匹配)

    Girls and Boys Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  8. poj2239 poj1274【二分匹配】

    题意: 就是尽可能的选多的课 思路: 把课程和上课的时间看作二分图 跑一跑二分匹配就好了 #include<iostream> #include<cstdio> #includ ...

  9. 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 ...

随机推荐

  1. MVC接收以post形式传输的各种参数

    近日研究用wcf框架接收同事Android端以post形式传输的各种类型的参数,来做处理.但研究过程中问题比较多,首先键值对的形式是实现了,传输int,string类型都不成问题,但是到传输文件的时候 ...

  2. javascript实现silverlight pivotViewer控件

    一时无事,就用js实现了一个silverlight pivotViewer控件来练手. 实现效果: silverlight PivotViewer说明地址:https://msdn.microsoft ...

  3. Mysql数据数据[字节、长度、数据范围]一览表

    1.mysql有哪些数据类型: 主要包括以下五大类: 整数类型:BIT.BOOL.TINY INT.SMALL INT.MEDIUM INT. INT. BIG INT 浮点数类型:FLOAT.DOU ...

  4. 如何清理多余的Windows桌面右键菜单

    删除多余的发送到选项 Win7使用一段时间后,我们可能会装很多软件,这时候右键菜单可能会变得很长,特别是“发送到(Send to)”里面的选项,有时候我们卸载软件之后在右键发送到菜单里还会有残存的选项 ...

  5. 您为这个网络适配器输入的IP地址xxx.xxx.xxx.xx已经分配给另一个适配器xxx...

    您为这个网络适配器输入的IP地址xxx.xxx.xxx.xx已经分配给另一个适配器‘xxx NIC’.... 2008年11月03日 星期一 08:51 问题现象:   在网卡的TCP/IP属性中无法 ...

  6. 真机测试,Xcode报错:process launch failed: Security

    解决办法:手机->通用->设备管理->信任开发商应用即可

  7. python记录

    1. 序列的分片操作:需要提供两个索引作为边界,第1个索引的元素包含在分片内,第2个索引的元素不包含在分片内. 为了能让分片部分能够包含列表的最后一个元素,必需提供最后一个元素的下一个元素所对应的索引 ...

  8. 多线程09-Lock和Condition

    1.概念 Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 2. ...

  9. PHPCMSv9 更改后台地址(测试)

    最新发布的PHPCMS V9由于采用了MVC的设计模式,所以它的后台访问地址是固定的,虽然可以通过修改路由配置文件来实现修改,但每次都修改路由配置文件对于我来说有点麻烦了,而且一不小心就会出错.这里使 ...

  10. TFS 如何恢复到指定版本

    一. 签出文件,然后获得指定版本. 二. 覆盖本地文件. 三.选择合并冲突. 四. 签入恢复的文件. 五. 解决冲突,选择抛弃服务器版本.