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

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

1≤n,m≤10^9, 0≤c≤nm, 1≤x≤n, 1≤y≤m
1≤T≤20。我们记 ∑c为某个测试点中，其 T 组输入数据的所有 c 的总和,∑c≤10^5

4
4 4 2
1 1
4 4
2 3 1
1 2
2 2 2
1 1
2 2
1 1 0

2
1
0
-1

ans = -1：nm-k < 2 或 nm - k = 2 且两个空地相邻

ans = 0：不连通

ans = 1：存在割顶

ans = 2：其余情况

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
//#include <windows.h>
using namespace std;

int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}

#define maxn 2400010
#define maxm 19200010
#define MMOD 5000007
#define X 523
#define x first
#define y second
#define pii pair <int, int>
#define mp(x, y) make_pair(x, y)
#define RND (rand() << 15 | rand())
#define LL long long

int cp, prime[MMOD], MOD;
bool Vis[MMOD];
void init() {
for(int i = 2; i < MMOD; i++) {
if(!Vis[i]) prime[++cp] = i;
for(int j = 1; i * prime[j] < MMOD && j <= cp; j++) {
Vis[i*prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
return ;
}

struct Hash {
int ToT, head[MMOD], nxt[maxn];
pii pos[maxn];

void init() { ToT = 0; memset(head, 0, sizeof(head)); return ; }

int Find(pii ps) {
int u = ((LL)ps.x * X + ps.y) % MOD;
for(int e = head[u]; e; e = nxt[e]) if(pos[e] == ps) return e;
return 0;
}
int Find(int x, int y) {
int u = ((LL)x * X + y) % MOD;
for(int e = head[u]; e; e = nxt[e]) if(pos[e] == mp(x, y)) return e;
return 0;
}
void Insert(pii ps) {
if(Find(ps)) return ;
int u = ((LL)ps.x * X + ps.y) % MOD;
nxt[++ToT] = head[u]; pos[ToT] = ps; head[u] = ToT;
return ;
}
void Insert(int x, int y) {
if(Find(x, y)) return ;
int u = ((LL)x * X + y) % MOD;
nxt[++ToT] = head[u]; pos[ToT] = mp(x, y); head[u] = ToT;
return ;
}
} Spc, Obs;

pii Near[maxn/24+10][30];
int cntn[maxn/24+10];
int dx[] = {-2, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, -3, 3, 0, 0},
dy[] = {-2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, 0, 0, -3, 3},
Dx[] = {-1, 1, 0, 0},
Dy[] = {0, 0, -1, 1};

struct Graph {
int m, head[maxn], nxt[maxm], to[maxm];
int fa[maxn];

void init() {
for(int i = 1; i <= Spc.ToT; i++) fa[i] = i;
return ;
}

int findset(int x){ return x == fa[x] ? x : fa[x] = findset(fa[x]); }

void AddEdge(int a, int b) {
//		printf("AddEdge(%d, %d)\n", a, b);
to[++m] = b; nxt[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; nxt[m] = head[a]; head[a] = m;
int u = findset(a), v = findset(b);
if(u != v) fa[v] = u;
return ;
}
} G;

bool vis[maxn];
int Q[maxn], hd, tl;
bool BFS(int s, int setu, int n, int m) {
hd = tl = 0; Q[++tl] = s; vis[s] = 1;
while(hd < tl) {
int u = Q[++hd]; pii& ps = Obs.pos[u];
for(int i = 1; i <= cntn[u]; i++) if(G.findset(Spc.Find(Near[u][i])) != setu) return 1;
for(int t = 0; t < 4; t++) {
pii tp = mp(ps.x + Dx[t], ps.y + Dy[t]);
if(1 <= tp.x && tp.x <= n && 1 <= tp.y && tp.y <= m) {
int v = Obs.Find(tp);
if(v && !vis[v]) Q[++tl] = v, vis[v] = 1;
}
}
}
return 0;
}

int low[maxn], dfn[maxn], clo;
bool iscut[maxn];
void dfs(int u, int fa) {
dfn[u] = ++clo; low[u] = clo;
//	printf("__dfs: %d %d\n", u, dfn[u]);
int son = 0;
iscut[u] = 0;
for(int e = G.head[u]; e; e = G.nxt[e]) if(G.to[e] != fa) {
if(!dfn[G.to[e]]) {
dfs(G.to[e], u);
if(low[G.to[e]] >= dfn[u]) iscut[u] = 1;
low[u] = min(low[u], low[G.to[e]]);
son++;
}
else low[u] = min(low[u], dfn[G.to[e]]);
}
//	printf("dfs: %d %d %d\n", u, low[u], dfn[u]);
if(!fa && son == 1) iscut[u] = 0;
return ;
}

//int Map[1010][1010];

int main() {
//	freopen("grid7.in", "r", stdin);
srand(20162523);
init();

int T = read();
while(T--) {
MOD = prime[RND%50000+cp-49999];
Spc.init(); Obs.init();

int n = read(), m = read(), c = read();
for(int i = 1; i <= c; i++) {
int x = read(), y = read();
Obs.Insert(x, y);
//			Map[x][y] = 1;
}
if(!c) Obs.Insert(1, 0), Obs.Insert(0, 1);
for(int i = 1; i <= Obs.ToT; i++) {
pii& ps = Obs.pos[i];
cntn[i] = 0;
for(int t = 0; t < (min(n, m) > 1 ? 24 : 28); t++) {
pii tp = mp(ps.x + dx[t], ps.y + dy[t]);
if(1 <= tp.x && tp.x <= n && 1 <= tp.y && tp.y <= m && !Obs.Find(tp)) {
Near[i][++cntn[i]] = tp, Spc.Insert(tp);
//					Map[tp.x][tp.y] = 2;
}
}
}
/*SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(Map[i][j] == 0) printf("??");
if(Map[i][j] == 1) printf("??");
if(Map[i][j] == 2) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE);
printf("??");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);
}
}
putchar('\n');
}*/

if(c >= (LL)n * m - 1){ puts("-1"); continue; }

G.init();
for(int i = 1; i <= Spc.ToT; i++) {
pii& ps = Spc.pos[i];
for(int t = 0; t < 4; t++) {
pii tp = mp(ps.x + Dx[t], ps.y + Dy[t]);
if(1 <= tp.x && tp.x <= n && 1 <= tp.y && tp.y <= m && Spc.Find(tp) && Spc.Find(tp) < i)
}
}

if(c == (LL)n * m - 2 && G.findset(1) == G.findset(2)){ puts("-1"); continue; }

memset(vis, 0, sizeof(vis));
bool is_0 = 0;
for(int i = 1; i <= Obs.ToT; i++) if(!vis[i] && cntn[i]) {
if(BFS(i, G.findset(Spc.Find(Near[i][1])), n, m)){ is_0 = 1; break; }
}
if(is_0){ puts("0"); continue; }

memset(dfn, 0, sizeof(dfn)); clo = 0;
bool is_1 = 0;
for(int i = 1; i <= Spc.ToT; i++) if(!dfn[i]) dfs(i, 0);
for(int i = 1; i <= Spc.ToT; i++) if(iscut[i]) {
pii& ps = Spc.pos[i];
for(int t = 0; t < 24; t++) if(max(abs(dx[t]), abs(dy[t])) < 2) {
pii tp = mp(ps.x + dx[t], ps.y + dy[t]);
if(!(1 <= tp.x && tp.x <= n && 1 <= tp.y && tp.y <= m) || Obs.Find(tp)){ is_1 = 1; break; }
}
if(is_1) break;
}
if(is_1){ puts("1"); continue; }

puts("2");
}

return 0;
}


BZOJ 不让用 time() 函数，本来随机种子是 time(0) 的。

posted @ 2017-06-29 22:37  xjr01  阅读(221)  评论(0编辑  收藏  举报