题解 寻宝
发现这个传送门是单向的就很烦
于是并查集缩点+有向图tarjan缩点+bitset可达性统计即可
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define fir first
#define sec second
#define make make_pair
#define pb push_back
//#define int long long
int n, m, k, q;
int dsu[N];
char s[N];
bool **mp;
pair<int, int> door[N];
vector<pair<int, int>> to[N];
const int dlt[][2]={{-1,0},{1,0},{0,1},{0,-1}};
inline int num(int x, int y) {return (x-1)*m+y;}
inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
namespace force{
bool vis[1010][1010];
queue<pair<int, int>> q2;
void bfs(int s, int t) {
vis[s][t]=1;
q2.push(make(s, t));
while (q2.size()) {
pair<int, int> u=q2.front(); q2.pop();
// cout<<"u: "<<u.fir<<' '<<u.sec<<endl;
for (int i=0; i<4; ++i) {
int x=u.fir+dlt[i][0], y=u.sec+dlt[i][1];
// cout<<"xy: "<<x<<' '<<y<<' '<<n<<' '<<m<<' '<<mp[x][y]<<endl;
if (x>=1&&x<=n&&y>=1&&y<=m&&!mp[x][y]&&!vis[x][y]) {
// cout<<"live: "<<x<<' '<<y<<endl;
vis[x][y]=1;
q2.push(make(x, y));
for (auto it:to[num(x, y)]) if (!vis[it.fir][it.sec]) {
vis[it.fir][it.sec]=1; q2.push(make(it.fir, it.sec));
}
}
}
}
}
void solve() {
for (int i=1,x1,y1,x2,y2; i<=q; ++i) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
memset(vis, 0, sizeof(vis));
bfs(x1, y1);
printf("%d\n", vis[x2][y2]);
}
exit(0);
}
}
namespace task1{
int head[N], size;
int dfn[N], low[N], sta[N], top, tot;
int left[N], id[N], deg[N], ltop;
bitset<25100> s[25100];
bool ins[N], vis[N];
map<pair<int, int>, bool> mp2;
queue<int> q2;
struct edge{int to, next;}e[N<<1];
inline void add(int s, int t) {e[++size].to=t; e[size].next=head[s]; head[s]=size;}
inline void uni(int s, int t) {if (find(s)!=find(t)) dsu[find(s)]=find(t);}
void tarjan(int u) {
dfn[u]=low[u]=++tot;
sta[++top]=u;
ins[u]=1;
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (!dfn[v]) {
tarjan(v);
low[u]=min(low[u], low[v]);
}
else if (ins[v]) low[u]=min(low[u], dfn[v]);
}
if (low[u]==dfn[u]) {
do {
uni(sta[top], u);
ins[sta[top--]]=0;
} while (sta[top+1]!=u);
}
}
void solve() {
// cout<<double(sizeof(s)+sizeof(head)*7+sizeof(ins)*2+sizeof(e)+sizeof(dsu)+sizeof(door)+sizeof(to))/1000/1000<<endl; return ;
for (int i=1; i<N; ++i) dsu[i]=i;
for (int i=1; i<=n; ++i) {
for (int j=1; j<=m; ++j) if (!mp[i][j]) {
for (int k=0; k<4; ++k) {
int x=i+dlt[k][0], y=j+dlt[k][1];
if (x>=1&&x<=n&&y>=1&&y<=m&&!mp[x][y]) {
int f1=find(num(i, j)), f2=find(num(x, y));
dsu[f1]=dsu[f2];
}
}
}
}
memset(head, -1, sizeof(head));
for (int i=1; i<=k; ++i) {
int f1=find(door[i].fir), f2=find(door[i].sec);
if (f1==f2) continue;
add(f1, f2);
}
for (int i=1; i<=n*m; ++i) if (!vis[find(i)]) left[++ltop]=find(i), vis[find(i)]=1;
for (int i=1; i<=ltop; ++i) if (!dfn[left[i]]) tarjan(left[i]);
memset(vis, 0, sizeof(vis)); tot=ltop=0;
for (int i=1; i<=n*m; ++i) if (!vis[find(i)]) left[++ltop]=find(i), vis[find(i)]=1, id[left[ltop]]=++tot;
memset(head, -1, sizeof(head)); size=0;
for (int i=1; i<=k; ++i) {
// cout<<"dor: "<<door[i].fir<<' '<<door[i].sec<<endl;
int s=id[find(door[i].fir)], t=id[find(door[i].sec)];
// cout<<"st: "<<s<<' '<<t<<endl;
if (s==t || mp2.find(make(s, t))!=mp2.end()) continue;
add(s, t); mp2[make(s, t)]=1; ++deg[t];
}
for (int i=1; i<=ltop; ++i) if (!deg[i]) q2.push(i);
while (q2.size()) {
int u=q2.front(); q2.pop();
s[u][u]=1;
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
s[v]|=s[u];
if (--deg[v]==0) q2.push(v);
}
}
for (int i=1,x1,y1,x2,y2; i<=q; ++i) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
int f1=id[find(num(x1, y1))], f2=id[find(num(x2, y2))];
// cout<<"f: "<<f1<<' '<<f2<<endl;
if (f1==f2 || s[f2][f1]) puts("1");
else puts("0");
}
exit(0);
}
}
signed main()
{
freopen("treasure.in", "r", stdin);
freopen("treasure.out", "w", stdout);
scanf("%d%d%d%d", &n, &m, &k, &q);
mp = new bool*[n+2];
for (int i=0; i<=n+1; ++i) {
mp[i]=new bool[m+2];
for (int j=0; j<=m+1; ++j) mp[i][j]=0;
}
for (int i=1; i<=n; ++i) {
scanf("%s", s+1);
for (int j=1; j<=m; ++j) mp[i][j]=s[j]=='#'?1:0;
}
for (int i=1,x1,y1,x2,y2; i<=k; ++i) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
door[i]=make(num(x1, y1), num(x2, y2));
to[num(x1, y1)].pb(make(x2, y2));
}
task1::solve();
// force::solve();
return 0;
}