[luoguP3355] 骑士共存问题(二分图最大独立集)
模型
二分图最大独立集,转化为二分图最大匹配,从而用最大流解决。
实现
首先把棋盘黑白染色,使相邻格子颜色不同。
把所有可用的黑色格子看做二分图X集合中顶点,可用的白色格子看做Y集合顶点。
建立附加源S汇T,从S向X集合中每个顶点连接一条容量为1的有向边,从Y集合中每个顶点向T连接一条容量为1的有向边。
从每个可用的黑色格子向骑士一步能攻击到的可用的白色格子连接一条容量为无穷大的有向边。
求出网络最大流,要求的结果就是可用格子的数量减去最大流量。
分析
用网络流的方法解决棋盘上的问题,一般都要对棋盘黑白染色,使之成为一个二分图。放尽可能多的不能互相攻击的骑士,就是一个二分图最大独立集问题。有关二分图最大独立集问题,更多讨论见《最小割模型在信息学竞赛中的应用》作者胡伯涛。
该题规模比较大,需要用效率较高的网络最大流算法解决。(使用Dinic+当前弧优化)
——代码
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#define INF 1e9
#define N 1000001
#define min(x, y) ((x) < (y) ? (x) : (y)) int n, m, cnt, tot, sum, s, t;
int map[][], head[N], to[N], val[N], next[N], dis[N], cur[N];
int dx[] = {-, -, , , , , -, -},
dy[] = {, , , , -, -, -, -}; inline int read()
{
int x = , f = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline void add2(int x, int y, int z)
{
to[cnt] = y;
val[cnt] = z;
next[cnt] = head[x];
head[x] = cnt++;
} inline void add(int x, int y, int z)
{
add2(x, y, z);
add2(y, x, );
} inline bool bfs()
{
int i, u, v;
std::queue <int> q;
memset(dis, -, sizeof(dis));
q.push(s);
dis[s] = ;
while(!q.empty())
{
u = q.front(), q.pop();
for(i = head[u]; i ^ -; i = next[i])
{
v = to[i];
if(val[i] && dis[v] == -)
{
dis[v] = dis[u] + ;
if(v == t) return ;
q.push(v);
}
}
}
return ;
} inline int dfs(int u, int maxflow)
{
if(u == t) return maxflow;
int v, d, ret = ;
for(int &i = cur[u]; i ^ -; i = next[i])
{
v = to[i];
if(val[i] && dis[v] == dis[u] + )
{
d = dfs(v, min(val[i], maxflow - ret));
ret += d;
val[i] -= d;
val[i ^ ] += d;
if(ret == maxflow) return ret;
}
}
return ret;
} int main()
{
int i, j, k, x, y;
n = read();
m = read();
s = , t = n * n + ;
memset(head, -, sizeof(head));
for(i = ; i <= m; i++)
{
x = read();
y = read();
map[x][y] = -;
}
for(i = ; i <= n; i++)
for(j = ; j <= n; j++)
if(!map[i][j])
{
map[i][j] = ++tot;
if((i + j) & ) add(s, tot, );
else add(tot, t, );
}
for(i = ; i <= n; i++)
for(j = ; j <= n; j++)
if(map[i][j] ^ - && (i + j) & )
for(k = ; k < ; k++)
{
x = i + dx[k];
y = j + dy[k];
if(x >= && x <= n && y >= && y <= n && map[x][y] ^ -) add(map[i][j], map[x][y], INF);
}
while(bfs())
{
for(i = s; i <= t; i++) cur[i] = head[i];
sum += dfs(s, INF);
}
printf("%d\n", tot - sum);
return ;
}
[luoguP3355] 骑士共存问题(二分图最大独立集)的更多相关文章
- 洛谷P3355 骑士共存问题 二分图_网络流
Code: #include<cstdio> #include<cstring> #include<queue> #include<vector> #i ...
- 【Codevs1922】骑士共存问题(最小割,二分图最大独立集转最大匹配)
题意: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入. 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个 ...
- 「CODVES 1922 」骑士共存问题(二分图的最大独立集|网络流)&dinic
首先是题目链接 http://codevs.cn/problem/1922/ 结果发现题目没图(心情复杂 然后去网上扒了一张图 大概就是这样了. 如果把每个点和它可以攻击的点连一条边,那问题就变成了 ...
- Cogs 746. [网络流24题] 骑士共存(最大独立集)
[网络流24题] 骑士共存 ★★☆ 输入文件:knight.in 输出文件:knight.out 简单对比 时间限制:1 s 内存限制:128 MB 骑士共存问题 «问题描述: 在一个n*n个方格的国 ...
- COGS746. [网络流24题] 骑士共存
骑士共存问题«问题描述:在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘 上某些方格设置了障碍,骑士不得进入. «编程任务:对于给定的n*n个方格的国际象棋棋盘和障碍标志 ...
- 【刷题】LOJ 6226 「网络流 24 题」骑士共存问题
题目描述 在一个 \(\text{n} \times \text{n}\) 个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入. 对于给定的 \(\t ...
- P3355 骑士共存问题
P3355 骑士共存问题 题目描述 在一个 n*n (n <= 200)个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n ...
- BZOJ3175:[TJOI2013]攻击装置(二分图最大独立集)
Description 给定一个01矩阵,其中你可以在0的位置放置攻击装置.每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2), ...
- [网络流24题] 骑士共存(cogs 746)
骑士共存问题«问题描述:在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘 上某些方格设置了障碍,骑士不得进入. «编程任务:对于给定的n*n个方格的国际象棋棋盘和障碍标志 ...
随机推荐
- 【转】Deactivating your reflector
原文:http://blog.csdn.net/cxwl3sxl/article/details/8072195 背景: 因为想破解一个.net写的程序,需要在visual studio 2010中使 ...
- 【转】瓜娃(guava)的API快速熟悉使用
http://www.cnblogs.com/snidget/archive/2013/02/05/2893344.html 1,大纲 让我们来熟悉瓜娃,并体验下它的一些API,分成如下几个部分: I ...
- python之道08
1.有如下文件,a1.txt,里面的内容为: 某某是最好的学校, 全心全意为学生服务, 只为学生未来,不为牟利. 我说的都是真的.哈哈 分别完成以下的功能: a,将原文件全部读出来并打印. 答案 f ...
- string 空值
string str; string mystr = ""; 则 str == mystr;
- 简单的cocos2dx笔试题
1.参数传递有几种方式?值传递.指针传递.引用传递 2.指针和引用有什么分别:如果传引用比传指针安全,为什么?如果我使用常量指针难道不行吗? 1.指针是一个变量,存储一个地址,指向内存的一个存储单元: ...
- 【转】再谈 最速下降法/梯度法/Steepest Descent
转载请注明出处:http://www.codelast.com/ 最速下降法(又称梯度法,或Steepest Descent),是无约束最优化领域中最简单的算法,单独就这种算法来看,属于早就“过时”了 ...
- PHPStorm+XDebug进行调试图文教程
这篇文章主要为大家详细介绍了PHPStorm+XDebug进行调试图文教程,内容很丰富,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 另外如果你们加载不出图片,另外的地址:转载地址https:// ...
- 每天一个linux命令(13):less命令
less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大.less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向前面翻 ...
- spartan6不能直接把时钟连到IO上
1.问题的提出:spartan6中不允许时钟信号直接连到IO口上面? 2.解决办法: ODDR2的使用 ODDR2Primitive: Double Data Rate Output D Flip-F ...
- PHP网站实现地址URL重定向
网站建设中,通常会用到网站地址URL的重定向,这样的好处是有利于你网站的SEO优化,也就是让你的网站实现伪静态,下面简单介绍一下实现的两种方法: 1.在Apache配置文件中设置重定向 首先找到Apa ...