刚了几个小时啊,这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. Apache DolphinScheduler 社区呼唤志愿者

    DolphinScheduler是什么? Apache DolphinScheduler 是一个分布式.易扩展并带有强大的可视化界面的大数据工作流调度系统. 2021 年 03 月 18 日正式成为 ...

  2. 051_末晨曦Vue技术_处理边界情况之provide和inject依赖注入

    provide和inject依赖注入 点击打开视频讲解更详细 在此之前,在我们描述访问父级组件实例的时候,展示过一个类似这样的例子: <google-map> <google-map ...

  3. CSS 布局(一):Flex 布局

    主轴和纵轴 对某一盒子模型添加display: flex;属性后,称之为 Flexible Box 模型(或称之为 flexbox),即弹性盒子模型,简称弹性盒子. 弹性盒子为子元素提供了强大的空间分 ...

  4. Word 文字错乱,接收方显示的字体与原版不一直

    原版文档使用字体的不是电脑上自带的常规字体,比如,黑软雅黑.黑体.宋体等字体.当把文档发送给其他人查阅时,字体发生了错乱,也就是字体与原版字体不一致. 需要打开"选项"设置,把非常 ...

  5. dpdk读字节,却触发了两次tlp

    在通过vfio框架透传设备到vm中,并且在vm中运行dpdk的驱动. 我们发现,dpdk偶尔的一次pread 2字节,却触发了两次tlp. 原因在于: do_io_rw { else if (fill ...

  6. 记一次twikoo引发的站点重大事故

    今天我测试私人博客的时候发现twikoo评论发生了错误,显示评论失败:0,我怀疑是我设置的twikoo安全域名有问题,所以我看了整个lssues,找到了我的解决方法! 1.关于配置安全域名后评论消失的 ...

  7. Spring源码-xml解析

    Spring使用SAX解析xml.SAX的全称是Simple APIs for XML,也即XML简单应用程序接口.与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式. ...

  8. 定时器控制单只LED灯

    点击查看代码 #include <reg51.h> #define uchar unsigned char #define uint unsigned int sbit LED=P0^0; ...

  9. k8s手动扩缩容

    1. 查询deploy副本数,ready数表示副本数 kubectl get deploy 2.通过命令直接扩容或者缩容,--replicas=1表示把my-dep缩容到副本数1,--replicas ...

  10. KingbaseES 数据库软件卸载

    关键字: KingbaseES.卸载   一.安装后检查 在安装完成后,可以通过以下几种方式进行安装正确性验证: 1. 查看安装日志,确认没有错误记录; 2. 查看开始菜单: 查看应用程序菜单中是否安 ...