这题暴力
n
2
n^2
n2很好想,暴力扩展
而一个房间能到达的地方是可合并的,如果这个房间u能到达一个房间v,那么房间v能到达的所有地方u都可以到达
我们发现如果一个门的钥匙在它右边,那么左边就过不去
在它左边同理
那么就分上面两种情况给
i
i
i和
i
+
1
i+1
i+1连一下边,拓扑排序就好了
时间复杂度
O
(
n
)
O(n)
O(n)(不会证)
Code:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=1e6+5;
int head[N],nxt[N],vis[N],tot=0;
struct data{int x,y;}d[N];
int n,m,p,id,to[N];
int pos[N],l[N],r[N],in[N];
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;++in[y];}
inline void init(){
pos[n]=-1;id=1;
for(int i=1;i<=n;++i){
to[i]=id;
if(pos[i]) l[id]=r[id]=id++;
}
--id;
for(int i=1;i<=m;++i){
int x=to[d[i].x],y=to[d[i].y];
pos[x]=y;
if(x<y) add(x,x+1);
else add(x+1,x);
}
}
inline int ok(int x,int y){
if(y<1 || y>id) return 0;
if(x<y) --y;
return l[x]<=pos[y]&&pos[y]<=r[x];
}
queue<int>q;
void dfs(){
for(int i=1;i<=id;++i)if(!in[i])q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
bool f=1;
while(f){
f=0;
while(ok(u,l[u]-1)) l[u]=l[l[u]-1],f=1;
while(ok(u,r[u]+1)) r[u]=r[r[u]+1],f=1;
}
for(int i=head[u];i;i=nxt[i]) if(!(--in[vis[i]])) q.push(vis[i]);
}
}
int main(){
n=read(),m=read(),p=read();
for(int i=1;i<=m;++i){
d[i].x=read(),d[i].y=read();
pos[d[i].x]=d[i].y;
}
init();dfs();
int x,y;
while(p--){
x=to[read()],y=to[read()];
if(l[x]<=y && y<=r[x]) puts("YES");
else puts("NO");
}
return 0;
}