Description

题库链接

给出一张 \(n\times m\) 的网格,在其中删去 \(c\) 个格子,问至少再删去几个能使得图上存在两点不连通,或输出无解。

多组询问,询问组数 \(T\) 。

\(1\leq T\leq 20,1\leq n,m\leq 10^9,\sum c\leq 10^5\)

Solution

观察题目,容易发现答案只会在 \(-1,0,1,2\) 之间,那么就可以随机输出其中一个数,以 \(\frac{1}{4^T}\) 的概率通过这道题

那么分类讨论。

  • 如果答案为 \(-1\) ,显然只有两种情况:只有剩一个格子,或者只有两个格子且两个格子相邻。这些是可以直接特判的。
  • 如果答案为 \(0\) ,显然是原图已经出现了不连通的状况。
  • 若果答案为 \(1\) ,那么原图存在一个点,使得删去这个点后图不联通,即原图存在割点。
  • 否则答案为 \(2\) 。

由于坐标过大,我们不能直接在原图上求解,考虑离散。其实注意到网格上留有的格子有用的只是与每个删掉的格子八连通的格子。

我们可以把这些格子留下来建图。不过有一种特殊的情况,那就是边界问题,举一个例子

.....
...00
...X1
...00
.....

如题原本是一个 \(5\times 5\) 的格子,在 \((3,5)\) 被删掉了一个格子,如果我们只考虑八连通,那么就会出现 \(\text{X}\) 是一个割点,然而在原图中并不是,所以就考虑将一个被删除的点的周围 \(5\times 5\) 的格子(共 \(24\) 个)都拿下来建新图。这样点数是 \(O(24\sum c)\) 的。

特判掉 \(-1,0\) 之后,就跑一遍 \(\text{tarjan}\) 判是否有割点即可。

Code

我用了 \(\text{map}\) ,在 \(\text{UOJ}\) 上过不去...( \(\text{bzoj}\) 过了就苟且偷生...233333...

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N = 100000+5;
const int w1[8] = {1, -1, 0, 0, 1, 1, -1, -1};
const int w2[8] = {0, 0, 1, -1, -1, 1, -1, 1};
void gi(int &x) {
char ch = getchar(); x = 0;
for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >= '0' && ch <= '9'; ch = getchar()) x = (x<<1)+(x<<3)+ch-48;
} int n, m, c, u, v, idx, color[N<<3], cnt;
struct pii {
int first, second;
pii (int _first = 0, int _second = 0) {first = _first, second = _second; }
bool operator < (const pii &b) const {
return first == b.first ? second < b.second : first < b.first;
}
bool operator == (const pii &b) const {return first == b.first && second == b.second; }
};
pii a[N], t, t1;
map<pii, int>id, mp;
queue<pii>Q, P;
struct tt {int to, next; }edge[N<<6];
int path[N<<3], top, rk[N<<3], iscut[N<<3], dfn[N<<3], low[N<<3], times; bool exist(int u, int v) {
t = a[lower_bound(a+1, a+c+1, pii(u, v))-a];
return t.first == u && t.second == v;
}
bool outof(int x, int y, int u, int d, int l, int r) {
return x < u || x > d || y < l || y > r;
}
void add(int u, int v) {edge[++top] = (tt){v, path[u]}; path[u] = top; }
bool judge() {
if (1ll*n*m-c <= 1) return false;
if (1ll*n*m-c >= 3) return true;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (!exist(i, j)) {
for (int k = 0; k < 4; k++) {
if (outof(i+w1[k], j+w2[k], 1, n, 1, m)) continue;
if (!exist(i+w1[k], j+w2[k])) return false;
}
return true;
}
}
}
void bfs(pii t) {
P.push(t); int u, v, u1, v1;
while (!P.empty()) {
t = P.front(); P.pop(); u = t.first, v = t.second; int c = color[id[t]];
for (int k = 0; k < 4; k++)
if (!outof(u1 = u+w1[k], v1 = v+w2[k], 1, n, 1, m) && !exist(u1, v1) && id.count(t1 = pii(u1, v1))) {
if (color[id[t1]]) continue;
color[id[t1]] = c; P.push(t1);
}
}
}
bool connect() {
while (!Q.empty()) {
t = Q.front(); Q.pop();
if (color[id[t]]) continue;
else color[id[t]] = ++cnt, bfs(t);
}
for (int Id = 1; Id <= c; Id++) {
int u = a[Id].first, v = a[Id].second, c = -1;
for (int i = -2; i <= 2; i++)
for (int j = -2; j <= 2; j++) {
if (outof(u+i, v+j, 1, n, 1, m) || exist(u+i, v+j)) continue;
t = pii(u+i, v+j);
if (c == -1) c = color[id[t]];
else if (c != color[id[t]]) return false;
}
}
return true;
}
void build(int u, int v) {
for (int i = -2; i <= 2; i++)
for (int j = -2; j <= 2; j++) {
if (outof(u+i, v+j, 1, n, 1, m) || exist(u+i, v+j)) continue;
t = pii(u+i, v+j);
int x = id.count(t) ? id[t] : (Q.push(t), id[t] = ++idx);
if (!outof(u+i+1, v+j, max(1, u-2), min(n, u+2), max(1, v-2), min(m, v+2)) && !exist(u+i+1, v+j)) {
t = pii(u+i+1, v+j);
int y = id.count(t) ? id[t] : (Q.push(t), id[t] = ++idx);
if (x > y) {if (!mp.count(pii(y, x))) add(x, y); add(y, x); mp[pii(y, x)] = 1; }
else {if (!mp.count(pii(x, y))) add(x, y); add(y, x); mp[pii(x, y)] = 1; }
}
if (!outof(u+i, v+j+1, max(1, u-2), min(n, u+2), max(1, v-2), min(m, v+2)) && !exist(u+i, v+j+1)) {
t = pii(u+i, v+j+1);
int y = id.count(t) ? id[t] : (Q.push(t), id[t] = ++idx);
if (x > y) {if (!mp.count(pii(y, x))) add(x, y); add(y, x); mp[pii(y, x)] = 1; }
else {if (!mp.count(pii(x, y))) add(x, y); add(y, x); mp[pii(x, y)] = 1; }
}
if (abs(i) <= 1 && abs(j) <= 1) rk[x] = 1;
}
}
void tarjan(int u, int fa) {
iscut[u] = 0; dfn[u] = low[u] = ++times; int sz = 0, v;
for (int i = path[u]; i; i = edge[i].next) {
if ((v = edge[i].to) == fa) continue;
if (!dfn[v]) {
++sz; tarjan(v, u);
if (low[v] >= dfn[u]) iscut[u] = 1;
low[u] = min(low[u], low[v]);
}else low[u] = min(low[u], dfn[v]);
}
if (fa == 0 && sz == 1) iscut[u] = 0;
}
void work() {
memset(path, top = idx = 0, sizeof(path)); id.clear(), mp.clear();
memset(dfn, times = 0, sizeof(dfn)); memset(rk, 0, sizeof(rk));
memset(color, cnt = 0, sizeof(color));
gi(n), gi(m), gi(c);
for (int i = 1; i <= c; i++) {
gi(u), gi(v); a[i] = pii(u, v);
}
sort(a+1, a+c+1); a[c+1] = pii(0, 0);
if (!judge()) {puts("-1"); return; }
for (int i = 1; i <= c; i++) build(a[i].first, a[i].second);
if (!connect()) {puts("0"); return; }
if (n == 1 || m == 1) {puts("1"); return; }
for (int i = 1; i <= idx; i++) {
if (!dfn[i]) tarjan(i, 0);
if (rk[i] && iscut[i]) {puts("1"); return; }
}
puts("2");
}
int main() {
int t; gi(t); while (t--) work();
return 0;
}

[NOI 2016]网格的更多相关文章

  1. [LOJ 2083][UOJ 219][BZOJ 4650][NOI 2016]优秀的拆分

    [LOJ 2083][UOJ 219][BZOJ 4650][NOI 2016]优秀的拆分 题意 给定一个字符串 \(S\), 求有多少种将 \(S\) 的子串拆分为形如 AABB 的拆分方案 \(| ...

  2. Noi 2016

    考砸只能说自己弱 Noi不是生活的全部, 人们也不会永远止步于失败. 大家加油 可以+我的qq:582744883

  3. 数据结构(线段树):NOI 2016 区间

    [问题描述] [输入格式] [输出格式] [样例输入] 6 3 3 5 1 2 3 4 2 2 1 5 1 4 [样例输出] 2 [样例说明] [更多样例] 下载 [样例 2 输入输出] 见目录下的 ...

  4. NOI 2016 优秀的拆分 (后缀数组+差分)

    题目大意:给你一个字符串,求所有子串的所有优秀拆分总和,优秀的拆分被定义为一个字符串可以被拆分成4个子串,形如$AABB$,其中$AA$相同,$BB$相同,$AB$也可以相同 作为一道国赛题,95分竟 ...

  5. NOI 2016 Day1 题解

    今天写了NOI2016Day1的题,来写一发题解. T2 网格 题目传送门 Description \(T\) 次询问,每次给出一个 \(n\times m\) 的传送门,上面有 \(c\) 个位置是 ...

  6. 字符串(后缀自动机):NOI 2016 优秀的拆分

    [问题描述] 如果一个字符串可以被拆分为 AABB 的形式,其中 A 和 B 是任意非空字符串, 则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 aabaabaa,如果令 A = aab, B ...

  7. noi 2016 游记

    先挖个坑..这回大概不会太监吧(大雾 day -2 下午起飞的飞机,晚上到了成都..把东西扔到旅馆后就组队外出觅食了... 街上人不多,逛了半天才发现一家卖本地小吃的小店. KPM:诶诶给我来碗酸辣粉 ...

  8. [NOI 2016]区间

    Description 在数轴上有 $n$ 个闭区间 $[l_1,r_1],[l_2,r_2],...,[l_n,r_n]$.现在要从中选出 $m$ 个区间,使得这 $m$ 个区间共同包含至少一个位置 ...

  9. 【BZOJ 4652】【NOI 2016】循环之美

    题目连接: 传送 题解: 真是一道好题…… 一: 一个分数$\frac{x}{y}$完全循环当其第一次出现时,当且仅当y与k互质,x与y互质,且y不等于1. 整数情况下y一定为1,即也满足以上判断. ...

随机推荐

  1. secureCRT端口转发功能突破防火墙限制

    这样一个场景:A是办公网络的一台windows主机,B是一台Linux堡垒机,C是生产环境一台Oracle主机, A只能访问B但A不能访问C,B可以访问到C,那怎样才可以使A机上的“ PLSQL De ...

  2. StringBuffer 去掉最后一个字符

    StringBuffer stringBuffer=new StringBuffer (); stringBuffer.append("aaa,"); stringBuffer.d ...

  3. 2-KNN(K最邻近算法)

    KNN基本思想: 1.事先存在已经分类好的样本数据(如分别在A类.B类.C类等) 2.计算待分类的数据(叫做新数据)与所有样本数据的距离 3.选择K个与新数据距离最近的的样本,并统计这K个样本所属的分 ...

  4. Docker 持续集成初次体验

    背景 在家的时候,实在不想做其他的,想起之前参加的一场关于docker的座谈会,于是想搞以下docker. 开始 在道客云上搞了一下持续集成,总体来说,比较好用的. 写了一个Go程序,就是之前写的发邮 ...

  5. 未能加载文件或程序集,PublicKeyToken=“**********”,或它的某一个依赖项。强名称验证失败。

    就是这种错误.这种错误怎么办? 以下步骤: (以上图dll为例) 1.看项目的Debug文件夹下是否有以下三个文件 2.看项目的.csproj文件下引用的报错dll的publickeytoken和版本 ...

  6. react-native项目之样式总结

    react native(以下简称rn)里面涉及到的样式规则都是在js文件中写的,一改pc端的在样式文件中定义规则,所以pc端开发习惯的童鞋转向开发rn项目时,可能会对样式感到有些奇怪:其实react ...

  7. Android 使用 NYTimes Stores 缓存 network request

    NYTimes Stores 是一个缓存库,在 2017年的 AndroidMakers 大会上被介绍过. https://github.com/NYTimes/Store 实现一个 Disk Cac ...

  8. Spring Boot log4j多环境日志级别的控制

    之前介绍了在<Spring boot中使用log4j>,仅通过log4j.properties对日志级别进行控制,对于需要多环境部署的环境不是很方便,可能我们在开发环境大部分模块需要采用D ...

  9. [vuejs] 终端npm run dev 不能自动打开浏览器运行项目解决办法

    终端执行: npm run dev 出现: I Your application is running here: http://localhost:8080 但并没有打开浏览器运行项目 解决办法: ...

  10. Docker - Docker与Vagrant的区别

    Docker Docker - HomePage Wiki - Docker Docker简介 Overview Docker 是一个开源的应用容器引擎,基于 Go 语言并遵从 Apache2.0 协 ...