BZOJ 4808 马 二分图最大独立集
题目应该就是最大独立集了吧,没什么了,平面图求最大独立集需要/2的,
WQH说加直接+双向边考研过,结果真的过了,应该是匈牙利算法寻找的
时候更加快了吧。(方便找边)
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#define N 207
using namespace std; const int lx[]={,,,,-,-,-,-};
const int ly[]={,,-,-,-,-,,}; int n,m;
int a[N][N],mark[N][N],du[N*N];
int cnt,head[N*N],next[N*N*N],rea[N*N*N];
int dui[N*N],flag[N*N]; void add(int u,int v){next[++cnt]=head[u],head[u]=cnt,rea[cnt]=v;}
bool dfs(int u)
{
for (int i=head[u];i!=-;i=next[i])
{
int v=rea[i];
if (flag[v]) continue;
flag[v]=;
if (!dui[v]||dfs(dui[v]))
{
dui[v]=u;
return ;
}
}
return ;
}
int main()
{
memset(head,-,sizeof(head));
scanf("%d%d",&n,&m);
int num=;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
{
scanf("%d",&a[i][j]);
mark[i][j]=(i-)*m+j;
if (a[i][j]) num++;
}
int x,y;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
if (a[i][j]==)
for (int k=;k<;k++)
{
x=i+lx[k],y=j+ly[k];
if(a[x][y]) continue;
if (x<=n&&x>=&&y>=&&y<=m) add(mark[i][j],mark[x][y]),add(mark[x][y],mark[i][j]);
}
memset(dui,,sizeof(dui));
int ans=;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
if (a[i][j]==)
{
memset(flag,,sizeof(flag));
ans+=dfs(mark[i][j]);
}
ans=n*m-num-ans/;
printf("%d",ans);
}
其实还有更优秀的思想
(图太丑,不管了)
这里可以,将平面图分成这样的格点图,玩过国际象棋的都知道,马是一黑一白交替着走的,
也就说,在同种颜色中,马不会相互攻击,那只需要计算一种颜色中最大独立集就可以了,
这样就是先记录可以填的位置,然后只需要操作一种颜色,连边出去,连向另外一个集合,
这样匹配的就是无法共存点,这样就OK了。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define hash(A,B) ((A)*m-m+B)
#define ok(A,B) (A>=1&&A<=n&&B>=1&&B<=m&&!mp[A][B])
#define N 40010
#define M 500010 int m,n,flow,sum;
int cnt,head[N],vis[N],match[N],mp[][];
struct Edge{int to,nxt;}e[M];
int dis[][]={{-,},{-,-},{,},{,-},{-,},{-,-},{,},{,-}}; void adde(int u,int v)
{
e[++cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
bool dfs(int u,int flag)
{
for(int i=head[u];~i;i=e[i].nxt)
{
int v=e[i].to;
if(vis[v]==flag) continue;
vis[v]=flag;
if(!match[v]||dfs(match[v],flag))
{
match[v]=u;
return ;
}
}
return ;
}
int main()
{
cnt=;sum=;flow=;
memset(head,-,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
for(int j=;j<=m;++j) scanf("%d",&mp[i][j]);
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
{
if(mp[i][j]) continue;sum++;
if((i^j)&)
{
for(int k=;k<;++k)
if(ok(i+dis[k][],j+dis[k][]))
{
adde(hash(i,j),hash(i+dis[k][],j+dis[k][]));
}
}
}
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
{
if(mp[i][j]) continue;
if((i^j)&)
{
int p=hash(i,j);
if(dfs(p,p)) flow++;
}
}
printf("%d\n",sum-flow);
return ;
}
BZOJ 4808 马 二分图最大独立集的更多相关文章
- BZOJ 4808: 马(二分图最大点独立集)
http://www.lydsy.com/JudgeOnline/problem.php?id=4808 题意: 思路: 这图中的两个马只能选一个,二选一,很像二分图吧,对能互吃的两个棋子连线,在所选 ...
- BZOJ4808马——二分图最大独立集
题目描述 众所周知,马后炮是中国象棋中很厉害的一招必杀技."马走日字".本来,如果在要去的方向有别的棋子挡住(俗 称"蹩马腿"),则不允许走过去.为了简化问题, ...
- 解题:BZOJ 4808 马
题面 以前写过的题,翻出来学习网络流写二分图匹配,因为复杂度更优秀,$Dinic$是$O(sqrt(n)m)$哒~ 原点向左部点连流量为$1$的边,左部点向对应右部点连流量为$1$的边,右部点向汇点连 ...
- bzoj 4808: 马【匈牙利算法】
网格图黑白染色,然后能互相攻击到的点之间连边,跑匈牙利算法最大匹配,答案是好点个数-最大匹配(最大独立集) 注意pao的时候只从一种颜色的格子统计即可 #include<iostream> ...
- 【Codevs1922】骑士共存问题(最小割,二分图最大独立集转最大匹配)
题意: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入. 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个 ...
- 长脖子鹿放置【洛谷P5030】二分图最大独立集变形题
题目背景 众周所知,在西洋棋中,我们有城堡.骑士.皇后.主教和长脖子鹿. 题目描述 如图所示,西洋棋的“长脖子鹿”,类似于中国象棋的马,但按照“目”字攻击,且没有中国象棋“别马腿”的规则.(因为长脖子 ...
- HDU 3829 - Cat VS Dog (二分图最大独立集)
题意:动物园有n只猫和m条狗,现在有p个小孩,他们有的喜欢猫,有的喜欢狗,其中喜欢猫的一定不喜欢狗,喜欢狗的一定不喜欢猫.现在管理员要从动物园中移除一些动物,如果一个小孩喜欢的动物留了下来而不喜欢的动 ...
- HDU3829(KB10-J 二分图最大独立集)
Cat VS Dog Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 125536/65536 K (Java/Others)Total ...
- BZOJ3175:[TJOI2013]攻击装置(二分图最大独立集)
Description 给定一个01矩阵,其中你可以在0的位置放置攻击装置.每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2), ...
随机推荐
- vijos 1190 繁忙的都市
描述 城市C是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造.城市C的道路是这样分布的:城市中有n个交叉路口,有些交叉路口之间有道路相连,两个交叉路口之间最多有一条道路 ...
- 自己开发的在线视频下载工具,基于Java多线程
比如这个在线视频: 我们可以正常播放,但是找不到下载按钮. 打开Chrome开发者工具,在Network标签页里能看到很多网络传输请求: 随便看一个请求的响应,发现类型为video,大小为500多k. ...
- win7上安装虚拟机并上网
一.安装Workstation Pro 二.下载CentOS-7-x86_64-DVD-1511.iso包 三.创建新的虚拟机,按照向导安装即可 四.使用cd /etc/sysconfig/netwo ...
- No-11.变量进阶
变量进阶 目标 变量的引用 可变和不可变类型 局部变量和全局变量 01. 变量的引用 变量 和 数据 都是保存在 内存 中的 在 Python 中 函数 的 参数传递 以及 返回值 都是靠 引用 传递 ...
- NULL Pointer Dereference(转)
0x00 漏洞代码 null_dereference.c: #include <linux/init.h> #include <linux/module.h> #include ...
- AT2172 Shik and Travel
题目描述: luogu 题解: 二分+暴力$vector$+$dfs$. 记录下所有可能的子树内合法方案,双指针+归并合并. 代码: #include<vector> #include&l ...
- bzoj5138 [Usaco2017 Dec]Push a Box
题目描述: bz luogu 题解: 暴力可以记录$AB$位置转移,这个时候状态是$n^4$的,无法接受. 考虑只记录$A$在$B$旁边时的状态,这个时候状态时$n^2$的. 所以说转移有两种,一种是 ...
- grub加密。
一.介绍 安全无小事 linux系统的安全分为很多方面,什么端口啊,什么网络啊,听着都特么烦,今天谈谈最简单明显的密码安全. 二.单用户模式 单用户模式个人觉得相当有用,可以用来修复系统,修改密码… ...
- 如何利用 CSS 动画原理,在页面上表现日蚀现象
效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/OELvrK 可交互视频教 ...
- Oracle联合主键
转https://www.cnblogs.com/king-xg/p/6721272.html alter table tablename add constraint unionkeyname pr ...