记录编号 425729 评测结果 AAAAAAAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2016]网格 最终得分 100
用户昵称 GravatarImone NOI2018Au 是否通过 通过
代码语言 C++ 运行时间 7.516 s
提交时间 2017-07-15 19:12:50 内存使用 173.89 MiB
显示代码纯文本
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#define ll long long
using namespace std;

const int MAXK = 100010;
const int MAXN = MAXK * 24;
const int HSIZE = 9999991;

namespace hash {
	int head[HSIZE], next[MAXN], coord[MAXN][2], id;
	inline void init() {
		id = 1; memset(head, 0, sizeof(head));
	}
	inline int find(int x, int y) {
		int i, hv = ((x * 3131 + y) & 0x7fffffff) % HSIZE;
		i = head[hv];
		while(i) {
			if(coord[i][0] == x && coord[i][1] == y) return i;
			i = next[i];
		}
		return 0;
	}
	inline bool ins(int x, int y) {
		if(!find(x, y)) {
			int hv = ((x * 3131 + y) & 0x7fffffff) % HSIZE;

			next[id] = head[hv]; 
			coord[id][0] = x; coord[id][1] = y;
			head[hv] = id++;
			return 1;
		}
		return 0;
	}
}

int MX, MY, K;

namespace conn {
	int head[MAXK], next[4*MAXK], tail[4*MAXK], id;
	inline void link(int u, int v) {
		next[id] = head[u]; tail[id] = v; head[u] = id++;
	}
	inline void init() {
		id = 1; memset(head, 0, sizeof(head));
	}

	int ccid[MAXK], ncc;
	void dfs(int u) {
		int i, v;
		ccid[u] = ncc;
		for(i=head[u];i;i=next[i]) {
			v = tail[i];
			if(!ccid[v]) dfs(v);
		}
	}
	void work() {
		int u;
		ncc = 0; memset(ccid, 0, sizeof(ccid));
		for(u=1;u<=K;u++) if(!ccid[u]) ncc++, dfs(u);
	}
}

namespace graph {
	int head[MAXN], next[4*MAXN], tail[4*MAXN], id;
	vector<int> node[MAXK];

	inline void link(int u, int v) {
		next[id] = head[u]; tail[id] = v; head[u] = id++;
	}
	inline void init() {
		id = 1; memset(head, 0, sizeof(head));
	}
	int dfn[MAXN], clock = 1;
	bool iscut[MAXN], hvcut;

	int ccid[MAXN], ncc;
	int dfs(int u, int fa) {
		int i, v, lowv;
		int lowu = dfn[u] = clock++, child = 0;
		ccid[u] = ncc;

		iscut[u] = 0;
		for(i=head[u];i;i=next[i]) {
			v = tail[i];
			if(!dfn[v]) {
				child++;
				lowv = dfs(v, u);
				lowu = min(lowu, lowv);
				if(lowv >= dfn[u]) iscut[u] = 1;
			}
			else if(dfn[v] < dfn[u] && v != fa) lowu = min(lowu, dfn[v]);
		}
		if(!fa && child <= 1) iscut[u] = 0;
		if(iscut[u]) {
			int x = hash::coord[u+K][0], y = hash::coord[u+K][1], dx, dy;
			
			bool ok = 0;
			for(dx=-1;dx<=1;dx++) for(dy=-1;dy<=1;dy++) if(dx || dy) {
				i = hash::find(x+dx, y+dy);
				if(i && i <= K) {
					ok = 1; break;
				}
			}
			if(ok) hvcut = 1;
		}
		return lowu;
	}

	inline int solve() {
		int i, t, u, x, y, dx, dy;
		hvcut = 0; clock = 1; ncc = 0;
		memset(dfn, 0, sizeof(dfn));
		for(u=K+1;u<hash::id;u++) if(!dfn[u - K]) ++ncc, dfs(u - K, 0);
		for(i=1;i<=conn::ncc;i++) {
			int Num = 0;
			for(t=0;t<node[i].size();t++) {
				x = hash::coord[node[i][t]][0];
				y = hash::coord[node[i][t]][1];
				for(dx=-1;dx<=1;dx++) for(dy=-1;dy<=1;dy++) if(dx || dy) {
					if((u = hash::find(x+dx, y+dy)) > K) {
						if(!Num) Num = ccid[u - K];
						else if(Num != ccid[u - K]) return 0;
					}
				}
			}
		}
		return hvcut ? 1 : ((MX == 1 || MY == 1) ? 1 : 2);
	}
}

const int fx[4] = {0, 1, 0, -1};
const int fy[4] = {1, 0, -1, 0};

inline void work() {
	int i, x, y, dx, dy, dir;
	hash::init();
	graph::init();
	conn::init();
	scanf("%d%d%d", &MX, &MY, &K);
	for(i=1;i<=K;i++) {
		scanf("%d%d", &x, &y); hash::ins(x, y);
	}

	if((ll)MX * MY - K <= 1) printf("-1\n");
	else if(K == 0) {
		if((ll)MX * MY - K == 2) printf("-1\n");
		else printf("%d\n", (MX == 1 || MY == 1) ? 1 : 2);
	}
	else {
		//link 0
		for(i=1;i<=K;i++) for(dir=0;dir<4;dir++) {
			x = hash::coord[i][0] + fx[dir]; y = hash::coord[i][1] + fy[dir];
			if(x = hash::find(x, y)) conn::link(i, x);
		}
		//get 0
		conn::work();
		for(i=1;i<=conn::ncc;i++) graph::node[i].clear();
		for(i=1;i<=K;i++) graph::node[conn::ccid[i]].push_back(i);
		//link
		for(i=1;i<=K;i++) for(dx=-2;dx<=2;dx++) for(dy=-2;dy<=2;dy++) if(dx || dy) {
			x = hash::coord[i][0] + dx; y = hash::coord[i][1] + dy;
			if(x >= 1 && y >= 1 && x <= MX && y <= MY) hash::ins(x, y);
		}
		//link side
		for(i=K+1;i<hash::id;i++) for(dir=0;dir<4;dir++) {
			x = hash::coord[i][0] + fx[dir]; y = hash::coord[i][1] + fy[dir];
			if((x = hash::find(x, y)) > K) graph::link(i - K, x - K);
		}

		int tmp = graph::solve();
		if((ll)MX * MY - K == 2 && tmp) tmp = -1;
		
		printf("%d\n", tmp);
	}
}

int main() {
    int size = 128 << 20;
    char *p = (char*)malloc(size) + size;  
    __asm__("movl %0, %%esp\n" :: "r"(p));
	
	freopen("NOI2016grid.in", "rt", stdin);
	freopen("NOI2016grid.out", "wt", stdout);

	int T; scanf("%d", &T);
	while(T--) work();
}