並不對勁的bzoj4651:loj2084:uoj220:p1173:[NOI2016]網格
題目大意
有一個\(n*m\)(\(n,m\leq10^9\))的網格,每個格子是空地或障礙(\(障礙數\leq10^5\))
定義兩塊空地連通,當且僅當它們是“相鄰的兩塊空地”或“存在一塊空地與這兩塊空地連通的兩塊空地”(也就是四連通)
求至少添加多少塊障礙物,使存在兩塊空地不連通,或者輸出-1表示無解
題解
當只有一塊空地或只有兩塊相鄰的空地時,無解
有解時,發現總能找到一個角落,使只用兩個障礙物就能將這個角落和外界分開(如圖)
也就是說,答案不超過2
當初始的障礙物已經將空地分成多個連通塊時,答案為0
當存在一個點,把該點刪去後空地會變成多個空地連通塊時(割點),答案為1
以上兩種都沒有,答案為2
如果n*m比較小的話,就可以直接將每塊空地與它上下左右的空地連邊,判連通性,tarjan找割點
但是n,m都比較大,存不下,考慮上一種建圖法中有哪些點是不必要的
連通性:
發現如果存在兩個點不連通,那麽一定存在兩個不連通的點是被一個障礙物連通塊隔開的
也就是說,可以通過判斷“是否存在一個障礙物連通塊,與它相鄰的所有空地中,存在兩塊空地不連通”來判斷整個圖是否連通
具體地,先找出所有障礙物連通塊,只把所有與這個連通塊相鄰(八連通)的空地互相連邊,判斷連通性
割點:
發現當網格的寬度不為1時,割點一定會與障礙相鄰(1)
將不與障礙相鄰的點刪去後,剩下的點才可能成為割點,將這些點組成的圖稱為“圖1”
但是這樣建圖後,會發現圖中的割點可能會和它周圍的沒被加入圖的空地相鄰,導致它不是割點
那麽就把與圖1中的點相鄰且不是障礙的點加入,得到圖2,求圖2是否有割點
根據(1),後加入的點在原圖中一定不是割點,所以通過判斷圖2是否存在一個割點在圖1中來判斷原圖是否有割點
代碼
#include<algorithm> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<ctime> #include<iomanip> #include<iostream> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define rep(i,x,y) for(register int i=(x);i<=(y);++i) #define dwn(i,x,y) for(register int i=(x);i>=(y);--i) #define view(u,k) for(int k=fir[u];k!=-1;k=nxt[k]) #define view2(u,k) for(int k=fir2[u];k!=-1;k=nxt2[k]) #define maxn 100010 #define maxnd 2500010 #define LL long long #define maxm (maxnd<<2) using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)&&ch!=‘-‘)ch=getchar(); if(ch==‘-‘)f=-1,ch=getchar(); while(isdigit(ch))x=(x<<1)+(x<<3)+ch-‘0‘,ch=getchar(); return x*f; } void write(int x) { if(x==0){putchar(‘0‘),putchar(‘\n‘);return;} int f=0;char ch[20]; if(x<0)putchar(‘-‘),x=-x; while(x)ch[++f]=x%10+‘0‘,x/=10; while(f)putchar(ch[f--]); putchar(‘\n‘); return; } int t,n,m,c,qx[maxn],qy[maxn],tim,cnts,cntnd,pos[maxnd],sop[maxnd],sop2[maxnd],maxy; int fir[maxnd],nxt[maxm],v[maxm],cnte,dfn[maxnd],low[maxnd],fa[maxnd],yes,stk[maxnd],tp; int fir2[maxn],nxt2[maxn<<2],v2[maxn<<2],cnte2,cntnd2,vis2[maxn],vis[maxnd]; struct seq{int x,y,ad;}a[maxnd],b[maxn]; map<int,int>lft,up; void ade(int u1,int v1){v[cnte]=v1,nxt[cnte]=fir[u1],fir[u1]=cnte++;} void ade2(int u1,int v1){v2[cnte2]=v1,nxt2[cnte2]=fir2[u1],fir2[u1]=cnte2++;} bool cmp1(seq x,seq y){return x.y==y.y?(x.x==y.x?x.ad<y.ad:x.x<y.x):x.y<y.y;} int f(int x){return fa[x]<0?x:fa[x]=f(fa[x]);} void merge(int x,int y){x=f(x),y=f(y);if(x==y)return;fa[x]+=fa[y],fa[y]=x;} void tar(int u,int fa) { int in=0; dfn[u]=low[u]=++tim; view(u,k) { if(!dfn[v[k]]) { tar(v[k],fa); if(yes)return; low[u]=min(low[u],low[v[k]]); if(low[v[k]]>=dfn[u]&&u!=fa&&a[sop[u]].ad==1){yes=1;return;} if(u==fa)in++; } low[u]=min(low[u],dfn[v[k]]); } if(u==fa&&in>=2&&a[sop[u]].ad==1){yes=1;return;} } int getr(int x,int y) { int l=1,r=cnts,ans=0; while(l<=r) { int mid=(l+r)>>1; if(a[mid].x==x&&a[mid].y==y)ans=max(ans,mid),l=mid+1; else if(a[mid].y<y||(a[mid].y==y&&a[mid].x<x))l=mid+1; else r=mid-1; } return ans; } void getstk(int u) { vis2[u]=1; int liml=max(1,a[sop2[u]].x-1),limr=min(n,a[sop2[u]].x+1),limd=max(1,a[sop2[u]].y-1),limu=min(m,a[sop2[u]].y+1); rep(i,liml,limr) rep(j,limd,limu) { int tmp=pos[getr(i,j)]; if(tmp&&!vis[tmp])stk[++tp]=tmp,vis[tmp]=1; } view2(u,k)if(!vis2[v2[k]])getstk(v2[k]); return; } int jug() { int res=1; rep(i,1,cntnd2) { tp=0; if(!vis2[i]) { getstk(i); rep(j,1,tp)vis[stk[j]]=0; rep(j,2,tp)if(f(stk[j])!=f(stk[1])){res=0;break;} if(!res)break; } } return res; } int main() { t=read(); while(t--) { n=read(),m=read(),c=read();cntnd=tim=cnts=cnte=yes=maxy=cntnd2=cnte2=0; rep(i,1,c*25)fir[i]=fa[i]=-1,dfn[i]=sop[i]=pos[i]=0;lft.clear(),up.clear(); rep(i,1,c) { qx[i]=read(),qy[i]=read(),fir2[i]=-1,sop2[i]=vis2[i]=0; int liml=max(1,qx[i]-2),limr=min(n,qx[i]+2),limd=max(1,qy[i]-2),limu=min(m,qy[i]+2); rep(j,liml,limr) rep(k,limd,limu) { a[++cnts].x=j,a[cnts].y=k,a[cnts].ad=min(2-abs(j-qx[i]),2-abs(k-qy[i])); } } sort(a+1,a+cnts+1,cmp1); int now=0; rep(i,1,cnts) { if(i==cnts||(a[i].x!=a[i+1].x||a[i].y!=a[i+1].y)) { if(a[i].ad==2) { int t1=up[a[i].y],t2=lft[a[i].x];cntnd2++; up[a[i].y]=-cntnd2;lft[a[i].x]=-cntnd2;sop2[cntnd2]=i; if(t1<0&&a[sop2[-t1]].x==a[i].x-1)ade2(-t1,cntnd2),ade2(cntnd2,-t1); if(t2<0&&a[sop2[-t2]].y==a[i].y-1)ade2(-t2,cntnd2),ade2(cntnd2,-t2); continue; } cntnd++;sop[cntnd]=i,pos[i]=cntnd; int t1=up[a[i].y],t2=lft[a[i].x];up[a[i].y]=cntnd;lft[a[i].x]=cntnd; if(t1>0)ade(t1,cntnd),ade(cntnd,t1),merge(t1,cntnd); if(t2>0)ade(t2,cntnd),ade(cntnd,t2),merge(t2,cntnd); } } int yeslink=jug(); if((LL)n*(LL)m<=2)write(-1); else if(c==0)write(min(n,m)==1?1:2); else if(cntnd==0)write(-1); else if(!yeslink)write(0); else if((LL)n*(LL)m-(LL)c<=2ll)write(-1); else if(min(n,m)==1)write(1); else { rep(i,1,cntnd){if(!dfn[i])tar(i,i);if(yes)break;} if(yes)write(1); else write(2); } } return 0; }
並不對勁的bzoj4651:loj2084:uoj220:p1173:[NOI2016]網格