刚了几个小时啊,这tm要是noi我怕不是直接滚粗了。我判答案为1的情况试了几种做法,最后终于想到了一个靠谱的做法,然后细节巨多,调了好久,刚拿到97分时代码有6.2KB了,后来发现有些东西好像没啥用就删到了5KB了,然后发现hack数据T掉了,就写了个哈希表换掉了map才过...真累

对了,我最开始判1是先求的割点再判断,只不过我感觉好像没有必要求割点啊,直接判也是对的,就把那段删掉了,然后在uoj上可以过,但别人貌似大多都求了割点?也许我这样做相当于求了割点?

讲做法吧(可能还有一些细节没考虑到,欢迎hack):

两蛐蛐的格子有公共点则称他们相邻(即一只蛐蛐可能和8只蛐蛐相邻),跳蚤则是有公共边(4条)。

答案肯定<=2,因为肯定存在一只在角落上的跳蚤。

判-1:\(nm-c=0 \ or\ nm-c=1 \ or\ (nm-c=2并且这两个跳蚤相邻)\)

判0:考虑每个有蛐蛐组成的连通块,对这里面的每只蛐蛐都把它8个方向的跳蚤拿出来,跳蚤们互相连边,答案为0当且仅当这里跳蚤组成的连通块个数>1.

判1:将边界视作一只假蛐蛐,然后对于所有的真假蛐蛐两两相邻则连边,对于所有的真蛐蛐都把它8个方向的跳蚤拿出来,对于某只跳蚤,把它替换成蛐蛐能达成目标当且仅当加入了它后附近的蛐蛐形成了环且环内部有跳蚤(就是枚举\(C_8^2\)种组合判)。具体的话,形成了环很好判看在不在一个连通块里就行了,至于环内部有没有跳蚤,由于环内部肯定有一只跳蚤是和新加入的这只蛐蛐相邻的,你只要判 在只考虑新蛐蛐的相邻点的情况下,这两只蛐蛐是否处于一个连通块内,不是说明肯定加入这只蛐蛐后就可以达成目标了。

举两个例子(网格从1开始编号,0代表跳蚤,1代表蛐蛐):

00000

01110

01000

01000

00000

你要判断(3,3)这个位置替换成蛐蛐可不可以,当你加入这只蛐蛐时,枚举到了(4,2)与(2,4)这两只蛐蛐,发现他们形成了环(但它包不住任意一只跳蚤),然后在只考虑这个方阵的情况下:

111

100

100

那两个点已经在一个连通块内了,不行。

00100

00100

00000

00100

00100

你要判断(3,3)这个位置替换成蛐蛐可不可以,当你加入这只蛐蛐时,枚举到了(2,3)与(4,3)这两只蛐蛐,发现他们形成了环,然后在只考虑这个方阵的情况下:

010

000

010

那两个点不在一个连通块内,加入蛐蛐后,左右就是完全隔开的两个跳蚤连通块了。因此可以。

最后剩余的情况就是2了。

然后中间要一些n=0 or W=1 or H=1的情况要小心。

复杂度是\(O(C_8^2n+8nlogn)\),用哈希表的话就是\(O(C_8^2n+8n)\),还有一点并查集的复杂度。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#define pl puts("lala")
#define cp cerr<<"lala"<<endl
#define fi first
#define se second
#define pb push_back
#define ln putchar('\n')
using namespace std;
inline int read()
{
char ch=getchar();int g=1,re=0;
while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
return re*g;
}
typedef long long ll;
typedef pair<int,int> pii; const int N=100011; struct HashMap
{
static const int mod=9999991;
static const int bas=1e9+1;
int head[mod+11],cnt;
int stk[1000050],top;
struct node
{
ll key; int next,val;
}e[1000050];
HashMap() {cnt=top=0;}
inline void insert(pii p,int v)
{
ll w=1ll*p.fi*bas+p.se;
int o=w%mod;
for(int i=head[o];i;i=e[i].next) if(e[i].key==w) return ;
e[++cnt]=(node){w,head[o],v}; head[o]=cnt;
stk[++top]=o;
}
inline int operator [] (pii p)
{
ll w=1ll*p.fi*bas+p.se;
int o=w%mod;
for(int i=head[o];i;i=e[i].next) if(e[i].key==w) return e[i].val;
return 0;
}
void clear()
{
cnt=0;
while(top) head[stk[top]]=0,top--;
}
}qid,zid;//q是蛐蛐,z是跳蚤 int move1[8]={0,1,1,1,0,-1,-1,-1}
,move2[8]={1,1,0,-1,-1,-1,0,1};
int W,H,n,tot=0;
pii p[N],zp[N*10];
bool vis[N]; int head[N*10],cnt=0;
struct node
{
int to,next;
}e[N*25];
inline void add(int x,int y)
{
e[++cnt]=(node){y,head[x]};head[x]=cnt;
}
int dfn[N*10],fa[N];
inline int find(int x)
{
if(fa[x]!=x) return fa[x]=find(fa[x]);
return fa[x];
} int nfa[9],bel[9];
inline int find2(int x)
{
if(nfa[x]!=x) return nfa[x]=find2(nfa[x]);
return nfa[x];
}
void dfs2(int u)
{
dfn[u]=1;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(dfn[v]) continue;
dfs2(v);
}
} queue<pii>q;
int stk[N],top=0,bel2[9];
void bfs(int sx,int sy)
{
q.push(pii(sx,sy)); vis[qid[pii(sx,sy)]]=1;
while(!q.empty())
{
int ux=q.front().fi,uy=q.front().se; q.pop();
for(int k=0;k<8;++k)
{
int x=ux+move1[k],y=uy+move2[k];
int ID=qid[pii(x,y)];
if(!ID||vis[ID]) continue;
stk[++top]=ID;
vis[ID]=1; q.push(pii(x,y));
}
}
}
int work(int cas)
{
W=read(); H=read(); n=read();
for(int i=1;i<=n;++i) vis[i]=0;
qid.clear();
for(int i=1;i<=n;++i)
{
p[i].fi=read(),p[i].se=read();
qid.insert(p[i],i);
}
if(1ll*W*H-n<=1) return -1;
if(1ll*W*H-n==2)
{
bool can=1;
for(int i=1;i<=W;++i)
{
for(int j=1;j<=H;++j) if(!qid[pii(i,j)])
{
for(int k=0;k<8;k+=2)
{
int x=i+move1[k],y=j+move2[k];
if(x<1||y<1||x>W||y>H) continue;
if(!qid[pii(x,y)]) {can=0;break;}
}
}
if(!can) break;
}
if(!can) return -1;
}
if(!n)
{
if(W==1||H==1) return 1;
else return 2;
}
for(int dot=1;dot<=n;++dot) if(!vis[dot])
{
top=0; stk[++top]=dot;
bfs(p[dot].fi,p[dot].se);
tot=0; zid.clear();
for(int i=1;i<=top;++i)
{
int x=p[stk[i]].fi,y=p[stk[i]].se;
for(int k=0;k<8;++k)
{
int nx=x+move1[k],ny=y+move2[k];
if(nx<1||ny<1||nx>W||ny>H) continue;
if(!qid[pii(nx,ny)]&&!zid[pii(nx,ny)])
++tot,zid.insert(pii(nx,ny),tot),zp[tot]=pii(nx,ny);
}
}
cnt=0;
for(int i=1;i<=tot;++i) head[i]=dfn[i]=0;
for(int i=1;i<=tot;++i)
{
int x=zp[i].fi,y=zp[i].se;
for(int k=0;k<8;k+=2)
{
int nx=x+move1[k],ny=y+move2[k];
if(nx<1||ny<1||nx>W||ny>H) continue;
int ID=zid[pii(nx,ny)];
if(ID) add(i,ID);
}
}
int blk=0;
for(int i=1;i<=tot;++i) if(!dfn[i]) blk++,dfs2(i);
if(blk>1) return 0;
}
if(W==1||H==1) return 1; tot=0; zid.clear();
for(int i=0;i<=n;++i) fa[i]=i;
for(int i=1;i<=n;++i)
{
int x=p[i].fi,y=p[i].se;
for(int k=0;k<8;++k)
{
int nx=x+move1[k],ny=y+move2[k];
if(nx<1||ny<1||nx>W||ny>H)
{
int r1=find(i),r2=find(0);
fa[r1]=r2;
continue;
}
int ID=qid[pii(nx,ny)];
if(!ID&&!zid[pii(nx,ny)])
++tot,zid.insert(pii(nx,ny),tot),zp[tot]=pii(nx,ny);
else if(ID)
{
int r1=find(i),r2=find(ID);
fa[r1]=r2;
}
}
}
for(int u=1;u<=tot;++u)
{
for(int i=0;i<8;++i) nfa[i]=i,bel[i]=0;
int x=zp[u].fi,y=zp[u].se;
for(int k=0;k<8;++k)
{
int nx=x+move1[k],ny=y+move2[k];
if(nx<1||ny<1||nx>W||ny>H) {bel[k]=find(0);continue;}
int ID=qid[pii(nx,ny)];
if(ID) bel[k]=find(ID);
else bel[k]=-1;
}
for(int k=0;k<8;++k)
{
if(bel[k]!=-1&&bel[k+1&7]!=-1)
{
int r1=find2(k),r2=find2(k+1&7);
nfa[r1]=r2;
}
if(!(k&1)&&bel[k]!=-1&&bel[k+2&7]!=-1)
{
int r1=find2(k),r2=find2(k+2&7);
nfa[r1]=r2;
}
}
for(int i=0;i<8;++i) bel2[i]=find2(i);
for(int i=0;i<8;++i) if(bel[i]!=-1)
{
for(int j=0;j<i;++j) if(bel[j]!=-1)
{
if(bel[i]==bel[j]&&bel2[i]!=bel2[j])
return 1;
}
}
}
return 2;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);freopen("1.out","w",stdout);
#endif
int T=read();
for(int cas=1;cas<=T;++cas) printf("%d\n",work(cas));
return 0;
}

uoj220【NOI2016】网格的更多相关文章

  1. BZOJ4651/UOJ220 [Noi2016]网格

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  2. UOJ220 [NOI2016] 网格 【割顶】【并查集】

    题目分析: 答案显然只有{-1,0,1,2}四种. 对于答案等于-1的情况,只有两种情况,一种是只剩一只跳蚤,另一种是只剩两只跳蚤且他们四连通,这个很好判. 对于答案等于0的情况,那说明联通块大于1, ...

  3. [UOJ#220][BZOJ4651][Noi2016]网格

    [UOJ#220][BZOJ4651][Noi2016]网格 试题描述 跳蚤国王和蛐蛐国王在玩一个游戏. 他们在一个 n 行 m 列的网格上排兵布阵.其中的 c 个格子中 (0≤c≤nm),每个格子有 ...

  4. BZOJ4651 & 洛谷1173 & UOJ220:[NOI2016]网格——题解(附debug数据)

    https://www.lydsy.com/JudgeOnline/problem.php?id=4651 https://www.luogu.org/problemnew/show/P1173#su ...

  5. 并不对劲的bzoj4651:loj2084:uoj220:p1173:[NOI2016]网格

    题目大意 有一个\(n*m\)(\(n,m\leq10^9\))的网格,每个格子是空地或障碍(\(障碍数\leq10^5\)) 定义两块空地连通,当且仅当它们是"相邻的两块空地"或 ...

  6. [Noi2016]网格

    来自FallDream的博客,未经允许,请勿转载,谢谢.   跳蚤国王和蛐蛐国王在玩一个游戏. 他们在一个 n 行 m 列的网格上排兵布阵.其中的 c 个格子中 (0≤c≤nm),每个格子有一只蛐蛐, ...

  7. 洛谷P1173 [NOI2016]网格

    这个码量绝对是业界大毒瘤...... 300行,6.5k,烦的要死...... 题意:给你一个网格图,里面有0或1.你需要把一些0换成1使得存在某两个0不四联通.输出最小的换的数量.无解-1. n,m ...

  8. [BZOJ4651][NOI2016]网格(Tarjan)

    下面直接给出结论,相关证明见官方题解. 1.若跳蚤数不超过1或仅有两只跳蚤且相邻,则答案为-1. 2.若跳蚤形成的连通块个数大于1,则答案为0. 3.若跳蚤之间建图存在割点,则答案为1. 4.否则为2 ...

  9. BZOJ4651 NOI2016网格(割点)

    首先显然可以通过孤立角落里的跳蚤使其不连通,所以只要有解答案就不会大于2.同样显然的一点是当且仅当跳蚤数量<=2且连通时无解.做法其实也很显然了:特判无解,若跳蚤不连通输出0,否则看图中是否无割 ...

  10. NOI2016

    luoguP1712 [NOI2016]区间 这是一道送分题. 对于我这种每天抄题解不动脑子思维僵化得厉害的智障选手就是送命题. 一直在想端点排序各种Treap搞... 正解: 已知一些区间,如何判断 ...

随机推荐

  1. 使用Django2.0.4集成钉钉第三方扫码登录

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_124 钉钉作为阿里旗下的一款免费移动通讯软件,受众群体越来越多,这里我们使用Django来集成一下钉钉的三方账号登录,首先注册钉钉 ...

  2. P4715 淘汰赛 - 记录

    P4715 淘汰赛 题目描述 有 2^n (n≤7) 个国家参加世界杯决赛圈且进入淘汰赛环节.我经知道各个国家的能力值,且都不相等.能力值高的国家和能力值低的国家踢比赛时高者获胜.1 号国家和 2 号 ...

  3. 基于vue2.0原理-自己实现MVVM框架之computed计算属性

    基于上一篇data的双向绑定,这一篇来聊聊computed的实现原理及自己实现计算属性. 一.先聊下Computed的用法 写一个最简单的小demo,展示用户的名字和年龄,代码如下: <body ...

  4. Taurus.MVC WebAPI 入门开发教程6:全局控制器DefaultController与全局事件。

    系列目录 1.Taurus.MVC WebAPI  入门开发教程1:框架下载环境配置与运行. 2.Taurus.MVC WebAPI 入门开发教程2:添加控制器输出Hello World. 3.Tau ...

  5. LuoguP1725 琪露诺 (动态规划)

    \(单调队列\) 或 \(堆\) 优化 #include <iostream> #include <cstdio> #include <cstring> #incl ...

  6. Redis 05 集合

    参考源 https://www.bilibili.com/video/BV1S54y1R7SB?spm_id_from=333.999.0.0 版本 本文章基于 Redis 6.2.6 Set 中的值 ...

  7. React报错之Unexpected default export of anonymous function

    正文从这开始~ 总览 当我们尝试使用默认导出来导出一个匿名函数时,会导致"Unexpected default export of anonymous function"警告.为了 ...

  8. Selenium 4 有哪些不一样?

    转载请注明出处️ 作者:测试蔡坨坨 原文链接:caituotuo.top/d59b986c.html 你好,我是测试蔡坨坨. 众所周知,Selenium在2021年10月13号发布了Selenium4 ...

  9. 轻松月薪过万,NISP证书含金量有多重|NISP管理中心|网安伴|nisp

    nisp一级证书含金量 NISP一级证书是面向各个行业工作人员信息安全意识普及化和网络信息安全基础培训的国家级验证.持NISP一级证书可以从信息安全保密较高的单位得到加分.证书由中国信息安全测评中心授 ...

  10. 好好回答下 TCP 和 UDP 的区别

    写了这么多篇关于 TCP 和 UDP 的文章,还没有好好聊过这两个协议的区别,这篇文章我们就来开诚布公的谈一谈. 关于 TCP 和 UDP ,想必大家都看过一张这样的图. 有一个小姑娘在对着瓶口慢慢的 ...