刚了几个小时啊,这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. 5.6 NOI模拟

    \(5.6\ NOI\)模拟 明天就母亲节了,给家里打了个电话(\(lj\ hsez\)断我电话的电,在宿舍打不了,只能用教练手机打了) 其实我不是很能看到自己的\(future,\)甚至看不到高三的 ...

  2. JVM学习之 内存结构

    目录 一.引言 1.什么是JVM? 2.学习JVM有什么用 3.常见的JVM 4.学习路线 二.内存结构 1. 程序计数器 1.1 定义 1.2作用 2. 虚拟机栈 2.1定义 2.2栈内存溢出 2. ...

  3. eclipse mave无法下载jar包

    解决方法: 先查看本地配置是否正确: 确保此处没有勾选 此处和自己配置的maven一致,没有则修改此处设置.然后项目上右键–>Maven–>Update Project 即可 . 如果还不 ...

  4. Android OOM 问题探究 -- 从入门到放弃

    一.前言 最近客户反馈了一些OOM的问题,很早之前自己也有简单了解过OOM的知识,但时间久远,很多东西都记不清了. 现在遇到这个OOM问题,也即趁此搜索了一些资料,对OOM问题做一些探究,把资料记录于 ...

  5. 【读书笔记】15《The Bridge of Madison County》

    廊桥遗梦(梅丽尔·斯特里普主演) 罗伯特·詹姆斯·沃勒 99个笔记 The Beginning   美[|diˈklainz]v 辞谢,谢绝(邀请等)( decline的第三人称单数 );(道路.物体 ...

  6. pathlib路径问题

    下面是我的文件框架 app ------ file1---- .py1 file2---- .py2 config.py 我在config文件中设置了变量参数 BASE_DIR = pathlib.P ...

  7. 大促活动如何抵御大流量 DDoS 攻击?

    每一次活动大促带来的迅猛流量,对技术人而言都是一次严峻考验.如果在活动期间遭受黑产恶意DDoS攻击,无疑是雪上加霜.电商的特性是业务常态下通常不会遭受大流量DDoS攻击,且对延迟敏感,因此只需要在活动 ...

  8. KingbaseES 工具sys_dump,sys_restore使用介绍

    说明: KingbaseES V8R6版本中自带数据库备份导出sys_dump,和备份恢复sys_restore工具. sys_dump:把KingbaseES数据库抽取为一个脚本文件或其他归档文件. ...

  9. KingbaseES V8R6C5B041手工创建集群测试案例

    ​ 案例说明: KingbaseES V8R6C5B041版本和以前的KingbaseES R6有一定的区别,增加了"securecmdd"的工具,并且在install.conf配 ...

  10. Springboot多属性文件配置

    Springboot 多属性文件配置 配置文件后缀有两种: .properties和.yml 要完成多属性配置需要自定义PropertySourcesPlaceholderConfigurer 这个B ...