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), ...
随机推荐
- codevs 4165 高精度求阶乘
时间限制: 1 s 空间限制: 256000 KB 题目等级 : 白银 Silver 题目描述 Description 用高精度计算出S=n! 其中"!"表示阶乘,例如:5!= ...
- 程序windows上可以上传附件,部署到 linux服务器后出现 “上传目录 不可写” 怎么解决?
这样的问题一般都是linux 下文件读写权限引起的,用 shell 命名到上传附件的目录(如 cd /data/www/project/upload/),然后执行 shell 文件权限设置: 例如 ...
- EF+linq的增删改查
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...
- 立个单调栈flag
http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=687&pid=1002
- 解决IIS7多域名绑定同一物理目录,设置不同的默认文档的问题
IIS7多域名绑定同一物理目录,设置不同的默认文档是没办法设置的,因为在一个物理目录下只有一个web.config,并且IIS7把默认文档设置写在这里,导致所有域名的默认文档设置共享.解决方法:1.进 ...
- Bootstrap历练实例:验证状态
验证状态 Bootstrap 包含了错误.警告和成功消息的验证样式.只需要对父元素简单地添加适当的 class(.has-warning. .has-error 或 .has-success)即可使用 ...
- 冒泡法排序参考(Java)
package com.swift; public class Maopao { //冒泡法 public static void main(String[] args) { int[] arr= { ...
- [LUOGU] P1049 装箱问题
题目描述 有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30,每个物品有一个体积(正整数). 要求n个物品中,任取若干个装入箱内,使箱子的剩余 ...
- windows终端输入pip install requests报错:Fatal error in launcher
emm今天群友发了个图,说他的pip报错,是这个问题 emmm这个问题我也不太懂,后来让他pip install requests这样操作,, 还是不管用,我寻思这个错咋回事,让他用 python ...
- 剑指Offer(书):调整数组顺序使奇数位于偶数前面
题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. public void ...