下面直接给出结论,相关证明见官方题解。

1.若跳蚤数不超过1或仅有两只跳蚤且相邻,则答案为-1。

2.若跳蚤形成的连通块个数大于1,则答案为0。

3.若跳蚤之间建图存在割点,则答案为1。

4.否则为2。

这样就有70分了。但是图太大了,显然有很多没用的跳蚤被统计进答案。

考虑到造成不连通的情况一定在蛐蛐附近,于是将每个蛐蛐周围5*5的格子中的24个跳蚤全部取出,内圈8个称为一级空地,外圈称为二级空地。之考虑这些点即可,复杂度就只与蛐蛐个数相关了。

将所有被取出的跳蚤建图,求连通块个数和割点即可。

几个注意点:

1.特判n=1或m=1的情况。

2.只有一级空地与在网格边缘的二级空地成为割点答案才能是0。

3.关于常数问题:不要用memset,判断元素是否存在用S.find(x)!=S.end()不要用S.count(x)。

4.下面代码在UOJ被叉掉了,以及O2会产生各种无解的错误,比如bool tag[N]如果写在int那行的上面就会被系统杀死。

 #include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mem(a) memset(a,0,sizeof(a))
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
using namespace std; const int N=;
const int dx[]={,,,,-},dy[]={,,,-,};
int T,n,m,c,cnt,tim,nd,id[][],dfn[N],low[N],fa[N],h[N],nxt[N<<],to[N<<];
bool tag[N];
struct P{ int x,y; }p[N],s[];
map<P,int>S;
bool operator <(const P &a,const P &b){ return (a.x==b.x) ? a.y<b.y : a.x<b.x; }
void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
int get(int x){ return (fa[x]==x) ? x : fa[x]=get(fa[x]); }
bool chk(int x,int y){ return x>= && x<=n && y>= && y<=m; } inline int rd(){
int x=; char ch=getchar();
while (ch<'' || ch>'') ch=getchar();
while (ch>='' && ch<='') x=(x<<)+(x<<)+(ch^),ch=getchar();
return x;
} bool tarjan(int x,int fa){
dfn[x]=low[x]=++tim; int son=;
For(i,x) if ((k=to[i])!=fa){
if (dfn[k]) low[x]=min(low[x],dfn[k]);
else{
if (tarjan(k,x)) return ;
son++; low[x]=min(low[x],low[k]);
if (((fa && low[k]>=dfn[x]) || (!fa && son>)) && tag[x]) return ;
}
}
return ;
} int main(){
freopen("grid.in","r",stdin);
freopen("grid.out","w",stdout);
for (scanf("%d",&T); T--; ){
scanf("%d%d%d",&n,&m,&c); cnt=; nd=; tim=; S.clear();
rep(i,,c) p[i].x=rd(),p[i].y=rd(),S[p[i]]=-;
if (1ll*n*m-c<=){ puts("-1"); continue; }
if (1ll*n*m-c==){
int tot=;
rep(i,,n) rep(j,,m) if (S.find((P){i,j})==S.end()) s[++tot]=(P){i,j};
if (abs(s[].x-s[].x)+abs(s[].y-s[].y)==) puts("-1"); else puts("");
continue;
}
rep(i,,c){
rep(x,-,) rep(y,-,) if (chk(p[i].x+x,p[i].y+y)){
int x1=p[i].x+x,y1=p[i].y+y;
if (S.find((P){x1,y1})==S.end())
id[x+][y+]=++nd,S[(P){x1,y1}]=nd,tag[nd]=,h[nd]=,dfn[nd]=,fa[nd]=nd;
else id[x+][y+]=S[(P){x1,y1}];
if (x1== || x1==n || y1== || y1==m || (abs(x)<= && abs(y)<=)) tag[id[x+][y+]]=;
}else S[(P){p[i].x+x,p[i].y+y}]=-,id[x+][y+]=-;
rep(x,,) rep(y,,) rep(k,,){
int x1=x+dx[k],y1=y+dy[k];
if (x1< || x1> || y1< || y1> || id[x][y]==- || id[x1][y1]==-) continue;
add(id[x][y],id[x1][y1]);
fa[get(id[x1][y1])]=get(id[x][y]);
}
}
bool flag=;
rep(i,,c){
int t=-;
rep(x,-,) rep(y,-,){
int w=S[(P){p[i].x+x,p[i].y+y}];
if (w==-) continue;
if (t==-) t=get(w); else { if (t!=get(w)){ flag=; break; } }
}
if (flag) break;
}
if (flag){ puts(""); continue; }
if (n== || m==){ puts(""); continue; }
rep(i,,nd) if (!dfn[i] && tarjan(i,)) { puts(""); flag=; break; }
if (!flag) puts("");
}
return ;
}

[BZOJ4651][NOI2016]网格(Tarjan)的更多相关文章

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

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

  2. BZOJ4651 NOI2016网格(割点)

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

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

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

  4. BZOJ4651/UOJ220 [Noi2016]网格

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

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

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

  6. UOJ#220. 【NOI2016】网格 Tarjan

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ220.html 前言 真是一道翔题. 草率题解 -1 的情况很好判,只有两种情况: n * m - c < 2 或者 ...

  7. [Noi2016]网格

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

  8. 洛谷P1173 [NOI2016]网格

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

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

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

随机推荐

  1. 【洛谷 P4016】 负载平衡问题(费用流)

    题目链接 环形均分纸牌,既然是网络流23题的那就用网络流做把. 套路拆点. 供需平衡. 源点向大于平均数的点的入点连流量为这个数减去平均数的差,费用为0的边,表示需要移走这么多. 小于平均数的点的出点 ...

  2. Angular 2.0 基础:服务

    什么是服务(Service) 在Angular 2 中我们提到的服务 service 一般指的是 哪些能够被其他组件或者指令调用的 单一的,可共享的 代码块.当然,通过服务可以将数据和组件分开,这样就 ...

  3. docker 镜像导入和导出

    使用 docker commit 即可把这个容器变为一个镜像 docker commit 8d93082a9ce1 ubuntu:myubuntu 这时候 docker 容器会被创建为一个新的 Ubu ...

  4. pip安装使用详解【转】

    转自:pip安装使用详解 – 运维生存时间http://www.ttlsa.com/python/how-to-install-and-use-pip-ttlsa/ pip类似RedHat里面的yum ...

  5. Nim 游戏、SG 函数、游戏的和

    Nim游戏 Nim游戏定义 Nim游戏是组合游戏(Combinatorial Games)的一种,准确来说,属于“Impartial Combinatorial Games”(以下简称ICG).满足以 ...

  6. Python如何实现文本转语音

    准备 我测试使用的Python版本为2.7.10,如果你的版本是Python3.5的话,这里就不太适合了. 使用Speech API 原理 我们的想法是借助微软的语音接口,所以我们肯定是要进行调用 相 ...

  7. .htaccess技巧: URL重写(Rewrite)与重定向(Redirect)

    URL重定向是.htaccess的重头戏,它可以将长地址转为短地址.将动态地址转为静态地址.重定向丢失的页面.防止盗链.实现自动语言转换等.笔者觉得难点是在正则表达式的运用和理解上. 实现所有这些神奇 ...

  8. [ python ] 面向对象 - 选课系统

    根据源程序进行改写:    原程序地址:http://www.cnblogs.com/lianzhilei/p/5985333.html  如有侵权立即删除.    感谢原作者将完整的代码提供参考.  ...

  9. hdu 5912(迭代+gcd)

    Fraction Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Su ...

  10. hdu 5839(三维几何)

    Special Tetrahedron Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...