zoukankan      html  css  js  c++  java
  • 并不对劲的bzoj4651:loj2084:uoj220:p1173:[NOI2016]网格

    题目大意

    有一个(n*m)(n,mleq10^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('
    ');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('
    ');
    	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;
    }
    
  • 相关阅读:
    2011年3月21日星期一
    AutoCAD VBA尺寸标注
    2011年3月22日星期二
    The method isEmpty() is undefined for the type String/String类型的isEmpty报错
    安全沙箱冲突..Error #2044: 未处理的 securityError:。 text=Error #2048: 安全沙箱冲
    Flash Builder4.6 无法启动,并且报 Failed to create the Java Virtual Machine (2—可能更好些)
    Flash Builder4.6 入门Demo_trace
    去掉JW Player水印及右键官方菜单
    JS如何判断单个radio是否被选中
    用JSON报错 java.lang.ClassNotFoundException: org.apache.commons.lang.exception.NestableRuntimeExcept .
  • 原文地址:https://www.cnblogs.com/xzyf/p/10391435.html
Copyright © 2011-2022 走看看