P4304 [TJOI2013]攻击装置

题目描述

给定一个01矩阵,其中你可以在0的位置放置攻击装置。 每一个攻击装置(x,y)都可以按照“日”字攻击其周围的8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2),(x+2,y-1),(x-1,y+2),(x-2,y+1),(x+1,y+2),(x+2,y+1)

求在装置互不攻击的情况下,最多可以放置多少个装置。

输入输出格式

输入格式:

第一行一个整数N,表示矩阵大小为N*N。

接下来N行每一行一个长度N的01串,表示矩阵。

输出格式:

一个整数,表示在装置互不攻击的情况下最多可以放置多少个装置。

输入输出样例

输入样例#1: 复制

3
010
000
100
输出样例#1: 复制

4

说明

30%数据N<=50

100%数据 N<=200


Solution

求最大点独立集,最大点独立集=点集-最大匹配

这道题因为是会相互连边,所以最后最大匹配数除以2就行了。

Code

#include<bits/stdc++.h>
using namespace std; struct Node {
int u, v, nex;
Node(int u = , int v = , int nex = ) :
u(u), v(v), nex(nex) { }
} Edge[]; int h[], stot;
void add(int u, int v) {
Edge[++stot] = Node(u, v, h[u]);
h[u] = stot;
} int n;
char s[][]; int zl[][] = {{-, -}, {-, -}, {, }, {, }, {, -}, {-, }, {-, }, {, -}};
int vis[], las[], to[], G[], id[][], t; bool dfs(int u) {
for(int i = h[u]; i; i = Edge[i].nex) {
int v = Edge[i].v;
if(vis[v] != t) {
vis[v] = t;
if(!las[v] || dfs(las[v])) {
las[v] = u; to[u] = v;
return ;
}
}
}
return ;
} bool pd(int x, int y) {
if(x < || y < || x > n || y > n || !G[id[x][y]]) return ;
return ;
} int main() {
int tot = , ans = ;
scanf("%d", &n);
for(int i = ; i <= n; i ++) scanf("%s", s[i] + );
for(int i = ; i <= n; i ++)
for(int j = ; j <= n; j ++) {
id[i][j] = (i - ) * n + j;
if(s[i][j] == '') G[id[i][j]] = , tot ++;
else G[id[i][j]] = ;
}
for(int i = ; i <= n; i ++)
for(int j = ; j <= n; j ++) {
if(!G[id[i][j]]) continue;
for(int k = ; k < ; k ++) {
int x = i + zl[k][], y = j + zl[k][];
if(!pd(x, y)) continue;
add(id[i][j], id[x][y] + n * n);
}
}
for(int i = ; i <= n * n; i ++)
if(!to[i] && G[i]) {
t ++;
ans += dfs(i);
}
printf("%d", tot - ans / );
return ;
}

P2172 [国家集训队]部落战争

题目描述

lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土。

A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住。lanzerb把自己的部落分成若干支军队,他们约定:

  1. 每支军队可以从任意一个城镇出发,并只能从上往向下征战,不能回头。途中只能经过城镇,不能经过高山深涧。

  2. 如果某个城镇被某支军队到过,则其他军队不能再去那个城镇了。

  3. 每支军队都可以在任意一个城镇停止征战。

  4. 所有军队都很奇怪,他们走的方法有点像国际象棋中的马。不过马每次只能走1*2的路线,而他们只能走R*C的路线。

lanzerb的野心使得他的目标是统一全国,但是兵力的限制使得他们在配备人手时力不从心。假设他们每支军队都能顺利占领这支军队经过的所有城镇,请你帮lanzerb算算至少要多少支军队才能完成统一全国的大业。

输入输出格式

输入格式:

第一行包含4个整数M、N、R、C,意义见问题描述。接下来M行每行一个长度为N的字符串。如果某个字符是'.',表示这个地方是城镇;如果这个字符时'x',表示这个地方是高山深涧。

输出格式:

输出一个整数,表示最少的军队个数。

输入输出样例

输入样例#1: 复制

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

4
输入样例#2: 复制

5 4 1 1
....
..x.
...x
....
x...
样例输出
输出样例#2: 复制

5

说明

100%的数据中,1<=M,N<=50,1<=R,C<=10。


Solution

比较轻松地可以想到最小路径覆盖问题,用最少的路径,经过所有点。

二分图是经典方法,每个点拆点,两点间有连边就在二分图上连边,最小路径=总点数-最大匹配。可以理解为,每一个匹配,就省去了一条路径(以入点为起点的路径可以由出点直接到达),所以最大匹配省去的路径是最多的。

最大匹配也可以用网络流实现。

注意空间....

Code

#include<bits/stdc++.h>
using namespace std; int G[][], n, m, r, c;
int zl[][] = {{, }, {, -}}; struct Node {
int u, v, nex;
Node(int u = , int v = , int nex = ) :
u(u), v(v), nex(nex) { }
} Edge[]; int h[], stot;
void add(int u, int v) {
Edge[++stot] = Node(u, v, h[u]);
h[u] = stot;
} bool check(int x, int y) {
if(x < || y < || x > m || y > n || !G[x][y]) return ;
return ;
} int las[], to[], vis[];
bool dfs(int u) {
for(int i = h[u]; i; i = Edge[i].nex) {
int v = Edge[i].v;
if(!vis[v]) {
vis[v] = ;
if(!las[v] || dfs(las[v])) {
to[u] = v; las[v] = u;
return ;
}
}
}
return ;
} int id[][], ans, tot;
char s[][];
int main() {
scanf("%d%d%d%d\n", &m, &n, &r, &c);
for(int i = ; i <= m; i ++) scanf("%s", s[i] + );
for(int i = ; i <= m; i ++) {
for(int j = ; j <= n; j ++) {
id[i][j] = (i - ) * n + j;
if(s[i][j] == '.') G[i][j] = , tot ++;
else G[i][j] = ;
}
}
for(int i = ; i <= m; i ++)
for(int j = ; j <= n; j ++) {
if(!G[i][j]) continue;
int x, y;
for(int k = ; k < ; k ++) {
x = i + zl[k][] * r, y = j + zl[k][] * c;
if(!check(x, y)) continue;
add(id[i][j], id[x][y] + n * m);
}
if(r != c) {
for(int k = ; k < ; k ++) {
x = i + zl[k][] * c, y = j + zl[k][] * r;
if(!check(x, y)) continue;
add(id[i][j], id[x][y] + n * m);
}
}
}
for(int i = ; i <= m; i ++) {
for(int j = ; j <= n; j ++)
if(!to[id[i][j]] && G[i][j]) {
memset(vis, , sizeof(vis));
ans += dfs(id[i][j]);
}
}
printf("%d", tot - ans);
return ;
}

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

  1. 洛谷P4304 [TJOI2013]攻击装置 题解

    题目链接: https://www.luogu.org/problemnew/show/P4304 分析: 最大独立集 最大独立集=总点数-最大匹配数 独立集:点集,图中选一堆点,这堆点两两之间没有连 ...

  2. 洛谷P4304 TJOI2013 攻击装置 (二分图匹配)

    题目大意:一个矩阵,一些点被拿掉,在棋盘上马走日,马之间不能落在同一点,求最多放几匹马. 采用对矩阵黑白染色,画个图可以发现:马可以走到的位置和他所处的位置颜色不同,将马和他可以走到的位置连边,最多可 ...

  3. 洛谷P2172 [国家集训队]部落战争 题解

    题目链接:https://www.luogu.org/problemnew/show/P2172 分析: 不要被[国家集训队]的标签吓到,其实这题不是很难. 本题可以对比P4304 [TJOI2013 ...

  4. 国家集训队 部落战争 网络流最小路径覆盖 洛谷P2172

    洛谷AC传送门! step1: 题目大意 有一张M x N的网格图,有一些点为“ * ”可以走,有一些点为“ x ”不能走,每走一步你都可以移动R * C 个格子(参考象棋中马的走法),且不能回头,已 ...

  5. 洛咕 P4304 [TJOI2013]攻击装置

    把坐标按照(x+y)%2染色可以发现这是个二分图 二分图最大独立集=点数-最大匹配 于是就是个算匹配的傻逼题了 // luogu-judger-enable-o2 #include<bits/s ...

  6. 洛谷P4003 [国家集训队2017]无限之环 网络流 最小费用最大流

    题意简述 有一个\(n\times m\)棋盘,棋盘上每个格子上有一个水管.水管共有\(16\)种,用一个\(4\)位二进制数来表示当前水管向上.右.下.左有个接口.你可以旋转除了\((0101)_2 ...

  7. BZOJ3175: [Tjoi2013]攻击装置

    题解: 最大点独立集...好像水过头了... 不过发现我二分图好像忘完了!!! 代码: #include<cstdio> #include<cstdlib> #include& ...

  8. BZOJ 3175: [Tjoi2013]攻击装置( 匈牙利 )

    黑白染成二分图, 然后不能同时选的就连边, 最大匹配数为m, t为不能放的数目, 则题目所求最大点独立集为 n*n-m-t -------------------------------------- ...

  9. 【BZOJ4808/3175】马/[Tjoi2013]攻击装置 最小割

    [BZOJ4808]马 Description 众所周知,马后炮是中国象棋中很厉害的一招必杀技."马走日字".本来,如果在要去的方向有别的棋子挡住(俗称"蹩马腿" ...

随机推荐

  1. libevent简介和使用【转】

    转自:http://www.open-open.com/lib/view/open1386510630330.html libevent是一个基于事件触发的网络库,memcached底层也是使用lib ...

  2. 使用netcat的正向 / 反向shell

    reverse shell bind shell reverse shell描述图: 在此示例中,目标使用端口4444反向连接攻击主机.-e选项将Bash shell发回攻击主机.请注意,我们也可以在 ...

  3. aarch64_g5

    gtkmm24-devel-2.24.5-2.fc26.aarch64.rpm 2017-02-11 18:17 620K fedora Mirroring Project gtkmm24-docs- ...

  4. 列表选择Spinner

    1.只用XML配置来显示列表 在res\values中添加一个arrays.xml 1 <?xml version="1.0" encoding="utf-8&qu ...

  5. 线性表应用--Josephus问题的解法(Python 版)

    线性表应用 --Josephus问题的解法(Python 版) Josephus问题描述:假设有n个人围坐一圈,现在要求从第k个人开始报数,报到第m个数的人退出.然后从下一个人开始继续报数并按照相同的 ...

  6. URL的井号

    2010年9月,twitter改版. 一个显著变化,就是URL加入了"#!"符号.比如,改版前的用户主页网址为 http://twitter.com/username 改版后,就变 ...

  7. java基础25 线程的常用方法、线程安全问题、死锁现象

    一.线程的常用方法 1.Thread(String name):初始化线程的名字2. setName(String name):设置线程的名字3. getName():返回线程的名字4. sleep( ...

  8. JVM性能调优监控工具——jps、jstack、jmap、jhat、jstat、hprof使用详解

    摘要: JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps.jstack.jmap.jhat.jstat.hprof等小巧的工具,本博客希望 ...

  9. DEDECMS去除后门隐患和漏洞以及冗余代码的方法

    链接:http://jingyan.baidu.com/article/4d58d541195bdb9dd4e9c029.html 工具/原料 织梦网站管理系统 sublime编辑器 方法/步骤 第一 ...

  10. 20155225 2006-2007-2 《Java程序设计》第四周学习总结

    20155225 2006-2007-2 <Java程序设计>第四周学习总结 教材学习内容总结 对"是一种"语法测试几次之后,总结一句:满足"是一种" ...