LOJ#2084. 「NOI2016」网格

$n,m \leq 1e9$,$n*m$的网格中有$c \leq 1e5$个是黑的,其他是白的。问:使至少两个白的不连通,最少需要再把几个白的涂黑。

可以发现答案是-1,0,1,2啦。-1要么没白的,要么一个白的,要么两个相邻白的。如果是两个不相邻白的答案就是0,这些可以特判掉。

其他的情况,可以建个图判连通、判割点。但网格太大了,可以发现连通的话只要关心所有黑点的周围八个白点之间的连通性即可,于是就记下这些点,离散化完分别按$x$和$y$排序来连边。但这样仍不能判割点,比如

0 0 0 0 0 0 0

0 0 0 0 0 0 0

0 0 0 0 0 0 0

0 0 0 0 0 0 1

0 0 0 0 0 0 0

0 0 0 0 0 0 0

0 0 0 0 0 0 0

这样,只把

0 0

0 1

0 0

拿出来建图,会出现3个割点,但不是我们想要的。为避免这种情况,需要把离散化后的周围区域再围一圈。变成这样:

0 0 0

0 0 0

0 0 1

0 0 0

0 0 0

注意到有些边界上的点不能“围”,比如上面例子,右边不能再围一圈。至于怎么围,其实离散化之前,把1,n加入$x$离散化数组中,1,m加入$y$离散化数组中,就可以直接围了,用hash保证不要重复加点即可。

然而,n=1和m=1需要特殊判断。。我就问出题人,出这种大分类大模拟大特判题是何居心。。

  1 //#include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 //#include<math.h>
  5 //#include<set>
  6 //#include<queue>
  7 //#include<bitset>
  8 //#include<vector>
  9 #include<algorithm>
 10 #include<stdlib.h>
 11 using namespace std;
 12 
 13 #define LL long long
 14 int qread()
 15 {
 16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
 17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
 18 }
 19 
 20 //Pay attention to '-' , LL and double of qread!!!!
 21 
 22 int T,n,m,c;
 23 #define maxn 2400011
 24 #define maxm 10000011
 25 
 26 int Abs(int x) {return x>0?x:-x;}
 27 
 28 struct Poi
 29 {
 30     int x,y,id;
 31     bool operator == (const Poi &b) const {return x==b.x && y==b.y;}
 32 }cc[maxn];
 33 bool cmpx(const Poi &a,const Poi &b) {return a.x<b.x || (a.x==b.x && a.y<b.y);}
 34 bool cmpy(const Poi &a,const Poi &b) {return a.y<b.y || (a.y==b.y && a.x<b.x);}
 35 
 36 int px[maxn],py[maxn],lx,ly;
 37 
 38 #define maxh 1000007
 39 struct Hash
 40 {
 41     struct Edge{int to,x,y,next;}edge[maxn]; int first[maxh],le;
 42     void clear() {memset(first,0,sizeof(first)); le=2;}
 43     int geth(int x,int y) {return (x*1000000000ll+y)%maxh;}
 44     void in(int x,int y,int id)
 45     {int h=geth(x,y); Edge &e=edge[le]; e.to=id; e.x=x; e.y=y; e.next=first[h]; first[h]=le++;}
 46     void insert(int x,int y,int id) {if (!~find(x,y)) in(x,y,id);}
 47     int find(int x,int y)
 48     {
 49         int h=geth(x,y);
 50         for (int i=first[h];i;i=edge[i].next) if (edge[i].x==x && edge[i].y==y) return edge[i].to;
 51         return -1;
 52     }
 53 }h,hh;
 54 
 55 const int dx[]={-1,0,1,-1,1,-1,0,1},
 56 dy[]={-1,-1,-1,0,0,1,1,1},
 57 ddx[]={-1,1,0,0},ddy[]={0,0,-1,1};
 58 
 59 int TOT,ANS,dfn[maxn],Time,low[maxn],top; Poi sta[maxn];
 60 struct Edge{int to,next;}edge[maxm]; int first[maxn],le=2;
 61 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
 62 void insert(int x,int y) {in(x,y); in(y,x);}
 63 
 64 void tarjan(int id,int fa)
 65 {
 66     TOT++;
 67     int son=0;
 68     dfn[id]=low[id]=++Time;
 69     for (int i=first[id];i;i=edge[i].next)
 70     {
 71         Edge &e=edge[i]; int u=e.to;
 72         if (!dfn[u])
 73         {
 74             sta[++top]=(Poi){id,u,0};
 75             son++;
 76             tarjan(u,id);
 77             low[id]=min(low[id],low[u]);
 78             if (low[u]>=dfn[id])
 79             {
 80 //                cout<<id<<' '<<u<<endl;
 81                 if (fa) ANS=1;
 82                 while (sta[top].x!=id || sta[top].y!=u) top--;
 83                 top--;
 84             }
 85         }
 86         else if (u!=fa && dfn[u]<dfn[id])
 87         {
 88             sta[++top]=(Poi){id,u,0};
 89             low[id]=min(low[id],dfn[u]);
 90         }
 91     }
 92     if (fa==0 && son>1) ANS=1;
 93 }
 94 
 95 int main()
 96 {
 97     T=qread();
 98     while (T--)
 99     {
100         n=qread(); m=qread(); c=qread();
101         for (int i=1;i<=c;i++) {cc[i].x=qread(); cc[i].y=qread();}
102         if (1ll*n*m-c<2) puts("-1");
103         else if (1ll*n*m-c==2)
104         {
105             if (c==0) {puts("-1"); continue;}
106             sort(cc+1,cc+1+c,cmpx);
107             int x1=0,x2=0,y1,y2;
108             for (int x=1,y=1,i=1;i<=c;i++,x+=(y==m),y=y==m?1:y+1)
109             {
110                 if (cc[i].x!=x || cc[i].y!=y)
111                 {
112                     if (!x1) x1=x,y1=y;
113                     else x2=x,y2=y;
114                     i--;
115                 }
116             }
117             if (x1==0) {x1=n; y1=m-1; x2=n; y2=m;}
118             else if (x2==0) {x2=n; y2=m;}
119             if (Abs(x1-x2)+Abs(y1-y2)==1) puts("-1");
120             else puts("0");
121         }
122         else
123         {
124             if (c==0)
125             {
126                 if (n==1 || m==1) puts("1");
127                 else puts("2");
128                 continue;
129             }
130             
131             int tc=c;
132             for (int i=1;i<=c;i++) cc[i].id=0;
133             lx=ly=0;
134             hh.clear();
135             for (int i=1;i<=c;i++) hh.insert(cc[i].x,cc[i].y,i);
136             for (int i=1,tmp=c;i<=tmp;i++)
137             {
138                 px[++lx]=cc[i].x; py[++ly]=cc[i].y;
139                 for (int j=0;j<8;j++)
140                 {
141                     int xx=dx[j]+cc[i].x,yy=dy[j]+cc[i].y;
142                     if (xx<=0 || xx>n || yy<=0 || yy>m || ~hh.find(xx,yy)) continue;
143                     c++; cc[c].x=xx; cc[c].y=yy; cc[c].id=cc[c-1].id+1; hh.insert(xx,yy,0);
144                     px[++lx]=xx; py[++ly]=yy;
145                 }
146             }
147             
148             px[++lx]=1; px[++lx]=n; sort(px+1,px+1+lx); lx=unique(px+1,px+1+lx)-px-1;
149             py[++ly]=1; py[++ly]=m; sort(py+1,py+1+ly); ly=unique(py+1,py+1+ly)-py-1;
150             for (int i=1;i<=c;i++) cc[i].x=lower_bound(px+1,px+1+lx,cc[i].x)-px,
151             cc[i].y=lower_bound(py+1,py+1+ly,cc[i].y)-py;
152             
153             hh.clear(); for (int i=1;i<=c;i++) hh.insert(cc[i].x,cc[i].y,cc[i].id);
154             for (int i=1;i<=ly;i++) if (!~hh.find(1,i))
155             {cc[c+1]=(Poi){1,i,cc[c].id+1}; c++; hh.insert(cc[c].x,cc[c].y,cc[c].id);}
156             for (int i=1;i<=ly;i++) if (!~hh.find(lx,i))
157             {cc[c+1]=(Poi){lx,i,cc[c].id+1}; c++; hh.insert(cc[c].x,cc[c].y,cc[c].id);}
158             for (int i=1;i<=lx;i++) if (!~hh.find(i,1))
159             {cc[c+1]=(Poi){i,1,cc[c].id+1}; c++; hh.insert(cc[c].x,cc[c].y,cc[c].id);}
160             for (int i=1;i<=lx;i++) if (!~hh.find(i,ly))
161             {cc[c+1]=(Poi){i,ly,cc[c].id+1}; c++; hh.insert(cc[c].x,cc[c].y,cc[c].id);}
162             
163             memset(first,0,sizeof(first)); le=2;
164             sort(cc+1,cc+1+c,cmpx);
165             for (int i=1;i<c;i++) if (cc[i].id && cc[i+1].id && cc[i].x==cc[i+1].x) insert(cc[i].id,cc[i+1].id);
166             sort(cc+1,cc+1+c,cmpy);
167             for (int i=1;i<c;i++) if (cc[i].id && cc[i+1].id && cc[i].y==cc[i+1].y) insert(cc[i].id,cc[i+1].id);
168             
169             TOT=ANS=Time=top=0;
170             memset(dfn,0,sizeof(dfn));
171             tarjan(1,0);
172             if (TOT<c-tc) puts("0");
173             else if ((n==1 || m==1) && (n*m>TOT)) puts("1");
174             else if (ANS) puts("1"); else puts("2");
175         }
176     }
177     
178     return 0;
179 }
View Code

 

posted @ 2018-07-01 21:57  Blue233333  阅读(289)  评论(0编辑  收藏  举报