题面描述
给一个
h
×
w
h\times w
h×w 的棋盘,有障碍。
q
q
q 次询问,每次把
k
k
k 个点变成障碍后询问能否找到两条从
(
1
,
1
)
(1,1)
(1,1) 到
(
h
,
w
)
(h,w)
(h,w) 的不相交的路径,询问独立。需要通过交互实现强制在线。
h
,
w
≤
1
0
3
h, w \leq 10^3
h,w≤103,
q
≤
1
0
4
q \leq 10^4
q≤104,
k
≤
10
k \leq 10
k≤10
题解
非常玄妙的结论题
考虑判断
(
1
,
1
)
(1,1)
(1,1)和
(
h
,
w
)
(h,w)
(h,w)是否连通如何解决
在最外圈除了起点和终点附近的地方都看成
#
\#
#
图片来源
类似上图
条件就是
(
h
+
1
,
0
)
(h+1,0)
(h+1,0)和
(
0
,
w
+
1
)
(0,w+1)
(0,w+1)是否八连通
然后拓展到判断是否有两条不交路径,条件就是判断
(
h
+
1
,
0
)
(h+1,0)
(h+1,0)和
(
0
,
w
+
1
)
(0,w+1)
(0,w+1)是否八连通或者在加入一个
#
\#
#后是否可以八连通
加入
k
k
k个
#
\#
#后怎么判断
1.
1.
1.直接连通
2.
2.
2.在
k
k
k个
#
\#
#周围加一个
#
\#
#可以达成八连通,可以枚举一下与
k
k
k个
#
\#
#距离为
2
2
2的位置
3.
3.
3.
k
k
k个
#
\#
#会接触到的连通块只有
O
(
k
)
O(k)
O(k)个,找出来互相判断一下能否通过加入一个
#
\#
#使两个连通块连通,并且判断一下两个连通块是否一个连着
(
h
+
1
,
0
)
(h+1,0)
(h+1,0),另一个连着
(
0
,
w
+
1
)
(0,w+1)
(0,w+1)
判断两个连通块能否通过加入一个
#
\#
#使两个连通块连通,可以通过预处理所有这样的连通块对,因为每个格子只会产生
O
(
1
)
O(1)
O(1)个连通块对,所以最多
O
(
h
w
)
O(hw)
O(hw)个连通块对,用哈希表存下,就可以
O
(
1
)
O(1)
O(1)回答询问
连通性可以用可撤销并查集
时间复杂度
O
(
h
w
+
q
k
(
k
+
log
k
)
)
O(hw+qk(k+\log k))
O(hw+qk(k+logk))
code \text{code} code
代码写得很长
#include<cstdio>
#include<algorithm>
#define ull unsigned long long
using namespace std;
void read(int &res)
{
res=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while('0'<=ch&&ch<='9') res=(res<<1)+(res<<3)+(ch^48),ch=getchar();
}
void readc(char &ch)
{
ch=getchar();
while(ch!='#'&&ch!='.') ch=getchar();
}
const int N=1010;
const int dx[8]={-1,-1,-1,0,0,1,1,1};
const int dy[8]={-1,0,1,-1,1,-1,0,1};
const int dex[16]={-2,-2,-2,-2,-2,-1,-1,0,0,1,1,2,2,2,2,2};
const int dey[16]={-2,-1,0,1,2,-2,2,-2,2,-2,2,-2,-1,0,1,2};
bool vis[N+10][N+10];
int h,w,q;
int id(int x,int y){return x*(w+2)+y+1;}
int fa[N*N+10],g[N*N+10],x[N+10],y[N+10];
vector<pair<int,int> > p;
int findfa(int x)
{
if(fa[x]==x) return x;
else
{
p.push_back({x,fa[x]});
return fa[x]=findfa(fa[x]);
}
}
void merge(int x,int y)
{
x=findfa(x),y=findfa(y);
if(x!=y)
{
p.push_back({x,fa[x]});
fa[x]=y;
}
}
int findfa1(int x)
{
if(fa[x]==x) return x;
else return fa[x]=findfa1(fa[x]);
}
void merge1(int x,int y)
{
x=findfa1(x),y=findfa1(y);
if(x!=y) fa[x]=y;
}
const ull mod=999979;
struct hash_table
{
int st[mod+10],tot;
struct edge
{
ull key;int last;
}e[N*N*4];
void insert(ull key)
{
ull h=key%mod;
for(int i=st[h];i!=0;i=e[i].last)
if(e[i].key==key)
return;
e[++tot].key=key;
e[tot].last=st[h];
st[h]=tot;
}
bool query(ull key)
{
ull h=key%mod;
for(int i=st[h];i!=0;i=e[i].last)
if(e[i].key==key)
return true;
return false;
}
}t;
int main()
{
// freopen("a.in","r",stdin);
read(h),read(w),read(q);
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++)
{
char ch;readc(ch);
vis[i][j]=(ch=='.');
}
vis[0][0]=vis[0][1]=vis[1][0]=vis[h+1][w+1]=vis[h][w+1]=vis[h+1][w]=true;
for(int i=0;i<=h+1;i++)
for(int j=0;j<=w+1;j++)
fa[id(i,j)]=id(i,j);
for(int i=0;i<=h+1;i++)
for(int j=0;j<=w+1;j++)
{
if(vis[i][j]) continue;
if(i>0&&!vis[i-1][j]) merge1(id(i,j),id(i-1,j));
if(j>0&&!vis[i][j-1]) merge1(id(i,j),id(i,j-1));
if(i>0&&j>0&&!vis[i-1][j-1]) merge1(id(i,j),id(i-1,j-1));
if(i>0&&j<w+1&&!vis[i-1][j+1]) merge1(id(i,j),id(i-1,j+1));
}
for(int i=0;i<=h+1;i++)
for(int j=0;j<=w+1;j++)
fa[id(i,j)]=findfa1(id(i,j));
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++)
{
if(!vis[i][j]) continue;
if(i==1&&j==1||i==h&&j==w) continue;
g[0]=0;
for(int d=0;d<8;d++)
if(!vis[i+dx[d]][j+dy[d]])
g[++g[0]]=fa[id(i+dx[d],j+dy[d])];
for(int k=1;k<=g[0];k++)
for(int w=k+1;w<=g[0];w++)
if(g[k]!=g[w])
t.insert((ull)N*N*g[k]+g[w]),t.insert((ull)N*N*g[w]+g[k]);
}
if(fa[id(h+1,0)]==fa[id(0,w+1)])
{
for(;q--;)
{
puts("NO\n");
fflush(stdout);
}
return 0;
}
for(int k;q--;)
{
read(k);
for(int i=1;i<=k;i++) read(x[i]),read(y[i]);
g[0]=0,g[++g[0]]=fa[id(h+1,0)],g[++g[0]]=fa[id(0,w+1)];
for(int i=1;i<=k;i++)
for(int d=0;d<8;d++)
if(!vis[x[i]+dx[d]][y[i]+dy[d]])
g[++g[0]]=fa[id(x[i]+dx[d],y[i]+dy[d])];
for(int i=1;i<=k;i++)
{
vis[x[i]][y[i]]=false;
for(int d=0;d<8;d++)
if(!vis[x[i]+dx[d]][y[i]+dy[d]])
merge(id(x[i],y[i]),id(x[i]+dx[d],y[i]+dy[d]));
}
bool ans=true;
if(findfa(id(h+1,0))==findfa(id(0,w+1))) ans=false;
else
{
for(int i=1;i<=k;i++)
{
for(int d=0;d<16;d++)
{
int Dx=x[i]+dex[d],Dy=y[i]+dey[d];
if(0<=Dx&&Dx<=h+1&&0<=Dy&&Dy<=w+1&&!vis[Dx][Dy])
{
if(findfa(id(h+1,0))==findfa(id(Dx,Dy))&&findfa(id(0,w+1))==findfa(id(x[i],y[i]))
||findfa(id(h+1,0))==findfa(id(x[i],y[i]))&&findfa(id(0,w+1))==findfa(id(Dx,Dy)))
{
ans=false;
break;
}
}
}
if(!ans) break;
}
if(ans)
{
for(int i=1;i<=g[0];i++)
{
for(int j=1;j<=g[0];j++)
if(g[i]!=g[j])
{
if(t.query((ull)N*N*g[i]+g[j]))
if(findfa(id(h+1,0))==findfa(g[i])&&findfa(id(0,w+1))==findfa(g[j]))
{
ans=false;
break;
}
}
if(!ans) break;
}
}
}
if(!ans) puts("NO");
else puts("YES");
fflush(stdout);
for(int i=1;i<=k;i++) vis[x[i]][y[i]]=true;
reverse(p.begin(),p.end());
for(auto v:p) fa[v.first]=v.second;
p.clear();
}
return 0;
}