刚了几个小时啊,这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. Vue 内置指令 && 自定义指令

    1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 & ...

  2. ARC129E Yet Another Minimization 题解 【网络流笔记】

    超神的建模,极其有借鉴意义/cy 注:该建模对应于最小割建模 对于 \(n\) 个数,每个数有 \(m\) 种取值的技巧 \(\forall i=1,2,\dots,n\),令 \(S=V_{i,0} ...

  3. 文件上传接入阿里云OSS

    目的:将文件交给阿里云进行管理,可避免文件对本地服务器资源的占用,阿里云OSS还可根据读写偏好选择合适的文件存储类型服务器,文件异地备份等 一.阿里云OSS基础了解(前提) 1.存储空间(Bucket ...

  4. Apache DolphinScheduler 使用文档(2-3/8):集群规划及环境准备

    本文章经授权转载,原文链接: https://blog.csdn.net/MiaoSO/article/details/104770720 目录 2. 集群规划 2.1 集群配置 2.2 软件版本 2 ...

  5. 金灿灿的季节 - Apache DolphinScheduler收获5位新Committer

    在这个金灿灿的收获季节,经过 Apache DolphinScheduler PPMC 们的推荐和投票,Apache DolphinScheduler 收获了 5 位新Committer .他们是:n ...

  6. Luogu1880 [NOI1995]石子合并 (区间DP)

    一个1A主席树的男人,沦落到褪水DP举步维艰 #include <iostream> #include <cstdio> #include <cstring> #i ...

  7. 慢SQL,压垮团队的最后一根稻草!

    一.什么是慢 SQL 什么是慢SQL?顾名思义,运行时间较长的 SQL 语句即为慢 SQL! 那问题来了,多久才算慢呢? 这个慢其实是一个相对值,不同的业务场景下,标准要求是不一样的. 我们都知道,我 ...

  8. 从零开始Blazor Server(12)--编辑菜单

    上个星期有点事,导致没法及时更新.现在我们继续更我们的从零开始系列. 这个系列也快要结束了,目前规划再有2-3篇,就结束了. 今天我们来说编辑菜单的问题,说实话菜单这种东西,你不更新代码加个页面,单独 ...

  9. github action 实现CI/CD

    两种github action 打包.Net Core 项目docker镜像推送到阿里云镜像仓库 1.GitHub Actions 是什么? 大家知道,持续集成由很多操作组成,比如抓取代码.运行测试. ...

  10. 【java】学习路线9-非静态内部类、外部类

    //内部类只能在其外部类当中使用//局部内部类:定义在方法里面//如果内部类和外部类有重名,就近原则在内部类中优先访问内部类.//如果想访问宿主类的同名成员,使用OuterClass.this.xxx ...