[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, ...
随机推荐
- 【CodeForces】576 D. Flights for Regular Customers
[题目]D. Flights for Regular Customers [题意]给定n个点m条边的有向图,每条边有di表示在经过该边前必须先经过di条边,边可重复经过,求1到n的最小经过边数.n,m ...
- 【洛谷P2014】选课
题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分,每门课有一 ...
- python3爬虫.4.下载煎蛋网妹子图
开始我学习爬虫的目标 ----> 煎蛋网 通过设置User-Agent获取网页,发现本该是图片链接的地方被一个js函数代替了 于是全局搜索到该函数 function jandan_load_im ...
- KS(Kolmogorov-Smirnov)(转)
来源:https://blog.csdn.net/u013421629/article/details/78217498 KS(Kolmogorov-Smirnov):KS用于模型风险区分能力进行评估 ...
- 关于servlet中重定向、转发的地址问题
先写一个正斜杠"/",再判断是服务器使用该地址还是网站使用该地址. 访问网络资源用/,访问硬盘资源用\. 例如: 转发: request.getRequestDispat ...
- JSON与JS的区别以及转换
JSON是什么?(JSON和JavaScript对象有什么区别?)如何把JS对象转化为JSON字符串,又如何把JSON字符串转化为JavaScript对象? JSON (JavaScript Obje ...
- php菜刀分析学习
这里以eval为例 我们知道, php中的eval能把字符串当代码执行: eval('phpcode'); 注意, 这里的代码要有分号结尾, 我们测试: 我们创建一个最简单的SHELL: <?p ...
- wget下载整个网站或特定目录
下载整个网站或特定目录 wget -c -k -r -np -p http://www.yoursite.com/path -c, –continue 断点下载 -k, –convert-links ...
- MySQL登录问题1045 (28000)处理步骤【原创】
MySQL登录问题1045 (28000) 俩台服务器主从复制,从的同步账号无法远程登录主服务器.报错ERROR 1045 (28000): Access denied for user 'root ...
- 数据结构与算法之KMP 字符串匹配
举例来说,有一个字符串"DSFFKFJD KFJLKFDLJFJ IWWJKJFJIA",我想知道,里面是否包含另一个字符串"JFJI",有的话就返回在原字符串 ...