题目

Source

http://www.lightoj.com/volume_showproblem.php?problem=1171

Description

Given an m x n chessboard where some of the cells are broken. Now you are about to place chess knights in the chessboard. You have to find the maximum number of knights that can be placed in the chessboard such that no two knights attack each other. You can't place knights in the broken cells.

Those who are not familiar with chess knights, note that a chess knight can attack eight positions in the board as shown in the picture below.

Input

Input starts with an integer T (≤ 125), denoting the number of test cases.

Each case starts with a blank line. The next line contains three integers m, n, K (1 ≤ m, n ≤ 200). Here m and n corresponds to the number of rows and the number of columns of the board respectively. Each of the next K lines will contain two integers x, y (1 ≤ x ≤ m, 1 ≤ y ≤ n) denoting that the cell(x, y) is broken already. No broken cell will be reported more than once.

Output

For each case of input, print the case number and the maximum number of knights that can be placed in the board considering the above restrictions.

Sample Input

2

8 8 0

2 5 4
1 3
1 4
2 3
2 4

Sample Output

Case 1: 32
Case 2: 6

分析

题目大概说一个n*m的国际象棋棋盘上有些格子不能放棋子,问最多能放几个骑士使得它们都不会处于互相攻击的状态。

棋盘黑白染色,形成二分图,然后就是二分图最大点独立集模型了,结果即为所有点数-二分图最大匹配。

代码

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 44444
#define MAXM 44444*22 struct Edge{
int v,cap,flow,next;
}edge[MAXM];
int vs,vt,NE,NV;
int head[MAXN]; void addEdge(int u,int v,int cap){
edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0;
edge[NE].next=head[v]; head[v]=NE++;
} int level[MAXN];
int gap[MAXN];
void bfs(){
memset(level,-1,sizeof(level));
memset(gap,0,sizeof(gap));
level[vt]=0;
gap[level[vt]]++;
queue<int> que;
que.push(vt);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(level[v]!=-1) continue;
level[v]=level[u]+1;
gap[level[v]]++;
que.push(v);
}
}
} int pre[MAXN];
int cur[MAXN];
int ISAP(){
bfs();
memset(pre,-1,sizeof(pre));
memcpy(cur,head,sizeof(head));
int u=pre[vs]=vs,flow=0,aug=INF;
gap[0]=NV;
while(level[vs]<NV){
bool flag=false;
for(int &i=cur[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){
flag=true;
pre[v]=u;
u=v;
//aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
aug=min(aug,edge[i].cap-edge[i].flow);
if(v==vt){
flow+=aug;
for(u=pre[v]; v!=vs; v=u,u=pre[u]){
edge[cur[u]].flow+=aug;
edge[cur[u]^1].flow-=aug;
}
//aug=-1;
aug=INF;
}
break;
}
}
if(flag) continue;
int minlevel=NV;
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==0) break;
level[u]=minlevel+1;
gap[level[u]]++;
u=pre[u];
}
return flow;
} bool map[222][222];
int dx[]={1,1,-1,-1,2,2,-2,-2};
int dy[]={2,-2,2,-2,1,-1,1,-1};
int main(){
int t,n,m,k;
scanf("%d",&t);
for(int cse=1; cse<=t; ++cse){
scanf("%d%d%d",&n,&m,&k);
memset(map,0,sizeof(map));
int a,b,tot=n*m;
while(k--){
scanf("%d%d",&a,&b);
--a; --b;
map[a][b]=1;
}
for(int i=0; i<n; ++i){
for(int j=0; j<m; ++j){
if(map[i][j]) --tot;
}
}
vs=n*m; vt=vs+1; NV=vt+1; NE=0;
memset(head,-1,sizeof(head));
for(int i=0; i<n*m; ++i){
int x=i/m,y=i%m;
if(map[x][y]) continue;
if(x+y&1) addEdge(i,vt,1);
else{
addEdge(vs,i,1);
for(int j=0; j<8; ++j){
int nx=x+dx[j],ny=y+dy[j];
if(nx<0 || nx>=n || ny<0 || ny>=m || map[nx][ny]) continue;
addEdge(i,nx*m+ny,1);
}
}
}
printf("Case %d: %d\n",cse,tot-ISAP());
}
return 0;
}

LightOJ1171 Knights in Chessboard (II)(二分图最大点独立集)的更多相关文章

  1. POJ1466 Girls and Boys(二分图最大点独立集)

    最大点独立集就是无向图中最多的两两不相邻的点集. 二分图最大点独立集=顶点数-二分图最大边独立集(二分图最大匹配) 这一题男女分别作YX部,如果x和y有浪漫关系则连边,如此构造二分图,答案显然就是最大 ...

  2. BZOJ 1143: [CTSC2008]祭祀river(二分图最大点独立集)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1143 题意: 思路: 二分图最大点独立集,首先用floyd判断一下可达情况. #include< ...

  3. BZOJ 4808: 马(二分图最大点独立集)

    http://www.lydsy.com/JudgeOnline/problem.php?id=4808 题意: 思路: 这图中的两个马只能选一个,二选一,很像二分图吧,对能互吃的两个棋子连线,在所选 ...

  4. 【bzoj4808】【马】二分图最大点独立集+简单感性证明

    (上不了p站我要死了,侵权度娘背锅) Description 众所周知,马后炮是中国象棋中很厉害的一招必杀技."马走日字".本来,如果在要去的方向有别的棋子挡住(俗称"蹩 ...

  5. POJ 2771 Guardian of Decency (二分图最大点独立集)

    Guardian of Decency Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 6133   Accepted: 25 ...

  6. HDU--3829--Cat VS Dog【最大点独立集】

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=3829 题意:动物园有n条狗.m头猫.p个小孩,每一个小孩有一个喜欢的动物和讨厌的动物.如今动物园要转移一些 ...

  7. 【POJ】1419:Graph Coloring【普通图最大点独立集】【最大团】

    Graph Coloring Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5775   Accepted: 2678   ...

  8. hdu 3829 Cat VS Dog 二分图匹配 最大点独立集

    Cat VS Dog Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others) Prob ...

  9. 【洛谷】4304:[TJOI2013]攻击装置【最大点独立集】【二分图】2172: [国家集训队]部落战争【二分图/网络流】【最小路径覆盖】

    P4304 [TJOI2013]攻击装置 题目描述 给定一个01矩阵,其中你可以在0的位置放置攻击装置. 每一个攻击装置(x,y)都可以按照“日”字攻击其周围的8个位置(x-1,y-2),(x-2,y ...

随机推荐

  1. c# 程序设计教程笔记

    值类型:[简单类型[整数类型(sbyte,byte,short,ushort,int uint,long....),字符类型),布尔类型,实数类型],结构类型, 枚举类型]. 引用类型:[类,委托,数 ...

  2. php 实用例子:购物车 涉及session与ajax

    login: <div>用户名:<input type="text" id="uid" /></div><div> ...

  3. 英文写作——冠词的使用(Use 0f Articles)

    1.使用'a','an','the'和不使用冠词的基本规则: <1>泛指,不可数名词不能有任何冠词 <2>泛指,可数,复数名词前不能有冠词 <3>泛指,可数,单数名 ...

  4. Python学习笔记——列表

    1.创建列表类型数据并给其赋值 >>> aList = [123,'abc',4.56,['inner','list'],7-9j] >>> aList [123, ...

  5. GIT本地配置和PUSH

    因为GIT使用的是LINUX命令,所以可以参考LINUX的相关命令 一.在本地配置好GIT仓库: 1.首先进入当前工程的目录:cd [filepath] (记住这里的目录应该用/,因为LINUX是这样 ...

  6. tomcat共享lib里面的jar包

    参考:http://shitouququ.blog.51cto.com/24569/1255094 1.在tomcat根目录下新建shared/lib目录结构,将项目的jar包放在此目录下,记得将项目 ...

  7. 群里分享的react的收藏一下!今日周末,改了个表单验证然后无所事事了!

    今日周末,改了个表单验证然后无所事事了,然后把昨天群里分享的react的收藏一下尽管现在还在研究angular和nodeJs毕竟刚刚开始用有点不熟...没准以后会研究一下react毕竟看着下面这张图还 ...

  8. 微信公众平台推出"微信保护"提升微信账号安全 附微信保护开启教程

    前两天小美女的微信公众平台要群发消息时提示需要绑定手机才能操作,当时还以为是动态ip的问题,今天微信公众平台安全中心就说升级了,原来那时已经在公测了.微信公众平台推出"微信保护", ...

  9. Linux进程间通信(七):消息队列 msgget()、msgsend()、msgrcv()、msgctl()

    下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信 -- 使用命名管道 一.什么是消息队列 消息队列提 ...

  10. C和指针 第七章 函数递归与迭代

    C语言通过运行时堆栈支持递归函数的实现,递归函数时直接或者间接调用自身的函数,经常有人拿斐波那契实现当做递归的实现,然后这样做效率并不高. n < 1;  Fib(1) =1 n = 2;  F ...