[BZOJ4651][NOI2016]网格(Tarjan)
下面直接给出结论,相关证明见官方题解。
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)的更多相关文章
- [UOJ#220][BZOJ4651][Noi2016]网格
[UOJ#220][BZOJ4651][Noi2016]网格 试题描述 跳蚤国王和蛐蛐国王在玩一个游戏. 他们在一个 n 行 m 列的网格上排兵布阵.其中的 c 个格子中 (0≤c≤nm),每个格子有 ...
- BZOJ4651 NOI2016网格(割点)
首先显然可以通过孤立角落里的跳蚤使其不连通,所以只要有解答案就不会大于2.同样显然的一点是当且仅当跳蚤数量<=2且连通时无解.做法其实也很显然了:特判无解,若跳蚤不连通输出0,否则看图中是否无割 ...
- BZOJ4651 & 洛谷1173 & UOJ220:[NOI2016]网格——题解(附debug数据)
https://www.lydsy.com/JudgeOnline/problem.php?id=4651 https://www.luogu.org/problemnew/show/P1173#su ...
- BZOJ4651/UOJ220 [Noi2016]网格
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- 并不对劲的bzoj4651:loj2084:uoj220:p1173:[NOI2016]网格
题目大意 有一个\(n*m\)(\(n,m\leq10^9\))的网格,每个格子是空地或障碍(\(障碍数\leq10^5\)) 定义两块空地连通,当且仅当它们是"相邻的两块空地"或 ...
- UOJ#220. 【NOI2016】网格 Tarjan
原文链接www.cnblogs.com/zhouzhendong/p/UOJ220.html 前言 真是一道翔题. 草率题解 -1 的情况很好判,只有两种情况: n * m - c < 2 或者 ...
- [Noi2016]网格
来自FallDream的博客,未经允许,请勿转载,谢谢. 跳蚤国王和蛐蛐国王在玩一个游戏. 他们在一个 n 行 m 列的网格上排兵布阵.其中的 c 个格子中 (0≤c≤nm),每个格子有一只蛐蛐, ...
- 洛谷P1173 [NOI2016]网格
这个码量绝对是业界大毒瘤...... 300行,6.5k,烦的要死...... 题意:给你一个网格图,里面有0或1.你需要把一些0换成1使得存在某两个0不四联通.输出最小的换的数量.无解-1. n,m ...
- UOJ220 [NOI2016] 网格 【割顶】【并查集】
题目分析: 答案显然只有{-1,0,1,2}四种. 对于答案等于-1的情况,只有两种情况,一种是只剩一只跳蚤,另一种是只剩两只跳蚤且他们四连通,这个很好判. 对于答案等于0的情况,那说明联通块大于1, ...
随机推荐
- LintCode 539: Move Zeroes
终于下决心开始刷题了! 选择LintCode而不是LeetCode主要是因为LintCode操作更顺手,希望能够坚持下去. 还是循序渐进吧,数据结构和算法的东西很久没碰都很生疏了,先找找感觉. 这是一 ...
- 始终要重载toString
本文涉及到的概念 1.重载toString方法的意义 2.两个注意事项 1.重载toString方法的意义 重载toString,返回关于当前实例的描述信息.这在调试错误,打印实例信息时,可以带来 ...
- 【BZOJ】1572: [Usaco2009 Open]工作安排Job
[题意]给定n项工作的截止时间和价值,每项工作需要1单位时间完成,求最大价值.n<=10^5. [算法]贪心+堆 [题解] 如果是访问到x时将d[x]前的点从价值最大的能加就加是错误的贪心,因为 ...
- inviteflood 洪泛滥工具
inviteflood是一种通过UDP/IP执行SIP/SDP INVITE消息泛洪的工具,描述可以参考:inviteflood Package Description 使用inviteflood工具 ...
- dataTables.js 响应式/package-lock.json 作用/eclipse 目录和工作区建立连接/navcat 导出数据库/vscode 快速进入方法
下班时间到啦! --下班都是他们的,而我,什么都没有. 什么周五放松日,什么五四青年节,什么都么有.继续总结一下今天遇到的问题. dataTables.js 响应式 使用dataTables.js创建 ...
- Axure RP 授权码
Axure RP 8.1.0.3372Licensee:KoshyKey:wTADPqxn3KChzJxLmUr5jTTitCgsfRkftQQ1yIG9HmK83MYSm7GPxLREGn+Ii6x ...
- ubuntu下中文输入法的配置,建议用fcitx
Fcitx [ˈfaɪtɪks] 是一个支持扩展的输入法框架.它有自己维护的三个输入法,拼音,区位和码表:还支持其他引擎,rime 中州韵,google-pinyin,sunpinyin.Fcitx ...
- 如何在LINUX中开机、登陆、退出、定时、定期自动运行程序
1.开机启动时自动运行程序 Linux加载后, 它将初始化硬件和设备驱动, 然后运行第一个进程init.init根据配置文件继续引导过程,启动其它进程.通常情况下,修改放置在 /etc/rc或 /et ...
- 64_m3
molequeue-doc-0.8.0-2.20161222giteb397e.fc26.no..> 05-Apr-2017 10:04 451570 molequeue-libs-0.8.0- ...
- 15个你不得不知道的Chrome dev tools的小技巧
转载自:https://www.imooc.com/article/2559 谷歌浏览器如今是Web开发者们所使用的最流行的网页浏览器.伴随每六个星期一次的发布周期和不断扩大的强大的开发功能,Chro ...