NC17896. [NOI2016]网格
描述
输入描述
每个输入文件包含多组数据。输入文件的第一行只有一个整数 T,表示数据的组数。保证 1≤T≤20。接下来依次输入 TT 组数据,每组数据的第一行包含三个整数 n, m, c。保证1≤n,m≤10^9,0≤c≤min(nm,105)接下来 c行,每行包含两个整数 x, y表示第 x 行,第 y 列的格子被一个蛐蛐占据(1≤x≤n,1≤y≤m)每一组数据当中,同一个蛐蛐不会被多次描述。同一行相邻的整数之间由一个空格隔开。1≤n,m≤10^9, 0≤c≤nm, 1≤x≤n, 1≤y≤m1≤T≤20。我们记 ∑c为某个测试点中,其 T 组输入数据的所有 c 的总和,∑c≤10^5
输出描述
对于每一组数据依次输出一行答案。
如果这组数据中,蛐蛐国王的希望不能被达成,输出-1。否则,输出被替换的跳蚤的个数的最小值
示例1
输入:
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
说明:
第一组数据就是问题描述中的例子。C++11(clang++ 3.9) 解法, 执行用时: 514ms, 内存消耗: 54352K, 提交时间: 2020-03-08 15:01:58
#include<map> #include<cmath> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef double dl; const int INF=2e9; const int N=1e5+5; const int M=N*24; const int P=666233; const int B=1e9+7; inline int read() { int X=0,w=0; char ch=0; while(!isdigit(ch)) { w|=ch=='-'; ch=getchar(); } while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct Hash { int cnt,head[P],nxt[M]; ll to[M]; inline void init() { cnt=0; memset(head,0,sizeof(head)); } inline void add(ll x,ll y) { ll v=(x*B+y); int u=v%P; to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } inline int qry(ll x,ll y) { ll v=(x*B+y); int u=v%P; for(int i=head[u];i;i=nxt[i]) if(to[i]==v) return i; return 0; } }mp1,mp2; struct node { int x,y; }p[N],q[M]; int im[M],n,m,c; int DX[4]={1,0,-1,0}; int DY[4]={0,1,0,-1}; int dx[24]={-2,-2,-2,-2,-2,-1,-1,-1,-1,-1,0,0,0,0,1,1,1,1,1,2,2,2,2,2}; int dy[24]={-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,1,2,-2,-1,0,1,2,-2,-1,0,1,2}; inline dl dis(dl x1,dl y1,dl x2,dl y2) { dl x=x1-x2,y=y1-y2; return sqrt(x*x+y*y); } struct edge { int to,nxt; }e[M*4]; int cnt,head[M],dfn[M],low[M],to[M],id,t,rtson; bool cut[M]; inline void add(int u,int v) { e[++cnt].to=v; e[cnt].nxt=head[u]; head[u]=cnt; } void tarjan(int u,int f) { to[u]=id; dfn[u]=low[u]=++t; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(!dfn[v]) { tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]&&f) cut[u]=1; if(!f) rtson++; } else if(f!=v) low[u]=min(low[u],dfn[v]); } if(!f&&rtson>=2) cut[u]=1; } bool vis1[M],vis2[M]; int dui[M],top; inline void init() { for(int i=1;i<=mp1.cnt;i++) vis2[i]=0; for(int i=1;i<=mp2.cnt;i++) cut[i]=head[i]=low[i]=dfn[i]=to[i]=vis1[i]=0; mp1.init(); mp2.init(); t=cnt=0; } inline void getnode(int x,int y,int iid) { vis2[iid]=1; for(int i=0;i<4;i++) { int nx=x+DX[i],ny=y+DY[i]; if(nx<1||nx>n||ny<1||ny>m) continue; int nxtid=mp1.qry(nx,ny); if(nxtid) continue; int tmp=mp2.qry(nx,ny); if(vis1[tmp]) continue; vis1[tmp]=1; dui[++top]=tmp; } for(int i=0;i<4;i++) { int nx=x+DX[i],ny=y+DY[i]; if(nx<1||nx>n||ny<1||ny>m) continue; int nxtid=mp1.qry(nx,ny); if(nxtid) { if(!vis2[nxtid]) getnode(nx,ny,nxtid); continue; } } for(int i=0;i<4;i++) { int nx=x+DX[i],ny=y+DY[i]; if(nx<1||nx>n||ny<1||ny>m) continue; vis1[mp2.qry(nx,ny)]=0; } } inline void solve() { for(int i=1;i<=mp2.cnt;i++) if(!dfn[i]) { id++; rtson=0; tarjan(i,0); } for(int i=1;i<=c;i++) { if(vis2[i]) continue; top=0; getnode(p[i].x,p[i].y,i); for(int j=1;j<=top;j++) if(to[dui[j]]!=to[dui[1]]) { puts("0"); return; } } if(n==1||m==1) { puts("1"); return; } for(int i=1;i<=mp2.cnt;i++) if(cut[i]&&im[i]==1) { puts("1"); return; } puts("2"); } inline bool find() { for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(!mp1.qry(i,j)) { for(int k=0;k<4;k++) { int x=i+DX[k],y=j+DY[k]; if(x<1||x>n||y<1||y>m) continue; if(!mp1.qry(x,y)) return 1; } return 0; } } } return 0; } int main() { int T=read(); while(T--) { init(); n=read(),m=read(),c=read(); for(int i=1;i<=c;i++) { p[i].x=read(),p[i].y=read(); mp1.add(p[i].x,p[i].y); } if((ll)n*m-c<=1||((ll)n*m-c==2&&find())) { puts("-1"); continue; } for(int i=1;i<=c;i++) { int x=p[i].x,y=p[i].y; for(int j=0;j<24;j++) { int nx=x+dx[j],ny=y+dy[j]; if(nx<1||nx>n||ny<1||ny>m||mp1.qry(nx,ny)) continue; int tmp=mp2.qry(nx,ny); if(!tmp) { mp2.add(nx,ny); if(dis(x,y,nx,ny)<1.9) im[mp2.cnt]=1; else im[mp2.cnt]=2; q[mp2.cnt]=(node){nx,ny}; } else { if(dis(x,y,nx,ny)<1.9) im[tmp]=1; else im[tmp]=min(2,im[tmp]); } } } for(int i=1;i<=mp2.cnt;i++) { int x=q[i].x,y=q[i].y; for(int j=0;j<4;j++) { int nx=x+DX[j],ny=y+DY[j]; if(nx<1||nx>n||ny<1||ny>m) continue; int tmp=mp2.qry(nx,ny); if(tmp&&im[tmp]) add(i,tmp); } } solve(); } return 0; }