这题细节很多啊,一开始没想通,浪费了很久。
总的来说,我是先对
n∗m≤5∗104
的数据暴力建图处理,然后对于大数据,答案必定大于等于0,先把所有蛐蛐形成的八连通块找出来,用并查集判断这些蛐蛐周围的跳蚤是否四联通,这样,就可以知道答案是否为0。如果不为0,再将每一个蛐蛐周围5*5范围内的跳蚤取出来建图,看看每个连通分量是否有割点即可。注意点数可达
2.2∗106
,最后我的点数是设成
2.5∗106
。这么多点,用stl的map存是不行的,要手写hashmap。
突然好心疼当年考场上的那些OIer们。
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int A=2500000,B=100010;
class graph{
public:
struct edge{
int to,next;
edge(int _to=0,int _next=0):to(_to),next(_next){}
}e[A*8];
int h[A],v,i,dfn[A],low[A],tim,tail,xb;
void dfs(int x,int fa){
tim++;
low[x]=dfn[x]=tim;
int child=0,i;
for (i=h[x];i;i=e[i].next){
int y=e[i].to;
if (!dfn[y]){
child++;
dfs(y,x);
int w=low[y];
if (w<low[x])low[x]=w;
if (w>=dfn[x])iscut[x]=1;
}else if(fa!=y && low[x]>dfn[y])low[x]=dfn[y];
}
if (fa<0 && child==1)iscut[x]=0;
}
public:
bool iscut[A];
void addedge(int x,int y){
e[++xb]=edge(y,h[x]);
h[x]=xb;
e[++xb]=edge(x,h[y]);
h[y]=xb;
}
int tarjan(){
tim=tail=0;
int block=0;
memset(iscut,0,sizeof iscut);
memset(dfn,0,sizeof dfn);
for(int i=1;i<=v;++i)
if(!dfn[i])dfs(i,-1),++block;
return block;
}
}g;
const int f1[8]={-1,-1,-1,0,0,1,1,1},f2[8]={-1,0,1,-1,1,-1,0,1};
int n,i,m,T,xb,cnt,w,x[B],y[B],u,v,s,t,j,a[A],b[A],c[A],f[A];
struct hashmap{
static const int p=20000003;
int h[p],nxt[A],a[A],xb,i;
pair<pair<int,int>,int> v[A];
inline int hash(pair<int,int> x){
return (1ll*x.first*(n-1)+x.second)%p;
}
inline bool count(pair<int,int> x){
int y=hash(x);
for(i=h[y];i;i=nxt[i])if(v[i].first==x)return 1;
return 0;
}
inline int& operator[](pair<int,int> x){
int y=hash(x);
for(i=h[y];i;i=nxt[i])if(v[i].first==x)break;
if(i)return v[i].second;
else{
v[++xb]=make_pair(x,0);
a[xb]=y;
nxt[xb]=h[y];
h[y]=xb;
return v[xb].second;
}
}
inline void insert(pair<pair<int,int>,int> x){
int y=hash(x.first);
v[++xb]=x;
a[xb]=y;
nxt[xb]=h[y];
h[y]=xb;
}
inline void clear(){
for(i=1;i<=xb;++i)h[a[i]]=0;
xb=0;
}
}M1,M2,M3;
pair<int,int> d[A];
pair<pair<int,int>,int> e[A];
inline bool in(int x,int y){
return 1<=x && x<=n && 1<=y && y<=m;
}
namespace SOL{
void main(){
memset(g.h,0,sizeof g.h);
g.xb=xb=0;
for(i=1;i<=n;++i)
for(j=1;j<=m;++j)
if(!M1.count(make_pair(i,j))){
M2[make_pair(i,j)]=++xb;
if(in(i,j-1) && !M1.count(make_pair(i,j-1)))g.addedge(M2[make_pair(i,j-1)],xb);
if(in(i-1,j) && !M1.count(make_pair(i-1,j)))g.addedge(M2[make_pair(i-1,j)],xb);
}
g.v=xb;
s=g.tarjan();
if(s>1)puts("0");
else if(1ll*n*m==cnt+2)puts("-1");
else{
for(i=1;i<=xb;++i)if(g.iscut[i])break;
if(i>xb)puts("2");
else puts("1");
}
}
}
void dfs(int x,int y,pair<int,int> fa){
M2.insert(make_pair(make_pair(x,y),0));
for(int i=0;i<8;++i){
int nx=x+f1[i],ny=y+f2[i];
pair<int,int> p=make_pair(nx,ny);
if(in(nx,ny) && p!=fa){
if(M1.count(p)){
if(!M2.count(p))dfs(nx,ny,make_pair(x,y));
}else d[++w]=p,M3.insert(make_pair(p,w));
}
}
}
int gfa(int a){
return f[a]==a?a:f[a]=gfa(f[a]);
}
int main(){
//freopen("NOI2016grid24.in","r",stdin);
//freopen("NOI2016grid.out","w",stdout);
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&cnt);
M1.clear();
M2.clear();
M3.clear();
for(i=1;i<=cnt;++i){
scanf("%d%d",x+i,y+i);
M1.insert(make_pair(make_pair(x[i],y[i]),0));
}
if(1ll*n*m-cnt<2){
puts("-1");
continue;
}
if(1ll*n*m<=50000){
SOL::main();
continue;
}
if(cnt==0){
puts(n==1 || m==1?"1":"2");
continue;
}
if(cnt==1){
if(n==1){
if(y[1]==1 || y[1]==m)puts("1");
else puts("0");
continue;
}
if(m==1){
if(x[1]==1 || x[1]==n)puts("1");
else puts("0");
continue;
}
if(((x[1]==1 || x[1]==n) && (y[1]==2 || y[1]==m-1)) ||
((x[1]==2 || x[1]==n-1)&& (y[1]==1 || y[1]==m)) || n==2 || m==2)puts("1");
else puts("2");
continue;
}
for(i=1;i<=cnt;++i)
if(!M2.count(make_pair(x[i],y[i]))){
//if(i%100==0)printf("%d\n",i);
M3.clear();
w=0;
dfs(x[i],y[i],make_pair(0,0));
for(int j=1;j<=w;++j)f[j]=j;
for(int j=1;j<=w;++j)
for(int k=0;k<8;++k)if(!f1[k] || !f2[k]){
int nx=d[j].first+f1[k],ny=d[j].second+f2[k];
int it=M3[make_pair(nx,ny)];
if(in(nx,ny) && it)f[gfa(j)]=gfa(it);
}
int j;
for(j=1;j<=w;++j)if(gfa(j)!=gfa(1))break;
if(j<=w)break;
}
if(i<=cnt){
puts("0");
continue;
}
M2.clear();
M3.clear();
xb=0;
memset(g.h,g.xb=xb=0,sizeof g.h);
w=0;
for(i=1;i<=cnt;++i)
for(j=0;j<8;++j){
u=x[i]+f1[j];
v=y[i]+f2[j];
if(in(u,v) && !M1.count(make_pair(u,v)) && !M2.count(make_pair(u,v)))
M2[make_pair(u,v)]=++xb,a[++w]=u,b[w]=v,c[w]=xb;
}
int z=xb;
i=w;
while(i){
u=a[i];
v=b[i];
s=c[i--];
for(int j=0;j<8;++j){
int x=u+f1[j],y=v+f2[j];
pair<int,int> p=make_pair(x,y);
if(in(x,y) && !M1.count(p) && !M2.count(p))M2[p]=++xb,a[++w]=x,b[w]=y,c[w]=xb;
}
}
for(i=1;i<=w;++i)e[i]=make_pair(make_pair(a[i],b[i]),c[i]);
std::sort(e+1,e+w+1);
for(i=2;i<=w;++i)
if(e[i-1].first.first==e[i].first.first && e[i].first.second==e[i-1].first.second+1)
g.addedge(e[i].second,e[i-1].second);
for(i=1;i<=w;++i)e[i]=make_pair(make_pair(b[i],a[i]),c[i]);
std::sort(e+1,e+w+1);
for(i=2;i<=w;++i)
if(e[i-1].first.first==e[i].first.first && e[i].first.second==e[i-1].first.second+1)
g.addedge(e[i].second,e[i-1].second);
g.v=xb;
s=g.tarjan();
for(i=1;i<=z;++i)if(g.iscut[i])break;
if(i>z)puts("2");
else puts("1");
}
return 0;
}