题目大意
迷宫可以描述为一个 n ∗ m n*m n∗m 的网格图,从上到下第 x x x 行,从左到右第 y y y 列的位置用 ( x , y ) (x,y) (x,y) 表示。
每个人可以在迷宫中移动移动若干次,每次可以向上下左右相邻的格子进行移动,但是无法移动到含有障碍物的格子。
除此以外,迷宫中还有 k k k 个传送门,每当一个人处在传送门入口所在的位置,就可以选择直接传送到出口所在的位置。
现在给出每个人的位置以及他们专属的宝藏的位置。
小 C
想知道,哪些人能够成功找到自己的宝藏。
能够成功找到自己的宝藏则输出 1 1 1,否则输出 0 0 0。
对于 100 % 100\% 100% 的数据, n × m ≤ 50000 , k ≤ 100 , q ≤ 100000 n \times m \leq 50000,k \leq 100,q \leq 100000 n×m≤50000,k≤100,q≤100000。
解题思路
首先明确,这题要注意传送门是单向的,即不能用并查集维护传送门。
先将二维表示成一维,即将 ( x , y ) (x,y) (x,y) 表示成 ( x − 1 ) ∗ m + y (x-1)*m+y (x−1)∗m+y。
然后用强连通缩点,再对传送门建单向边,跑 dfs
。(
k
≤
100
k \leq 100
k≤100)
没了。。。
CODE
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if(c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
int n, m, k, q;
char s[100007];
int mp[100007];
struct Grath
{
int tot, head[100007], to[100007 << 1], nxt[100007 << 1];
void add(int u, int v)
{
to[++tot] = v;
nxt[tot] = head[u];
head[u] = tot;
}
} e1, e2;
int cnt_node, cntn, dfn[100007], low[100007], id[100007];
stack<int> ss;
void tarjan(int u)
{
dfn[u] = low[u] = ++cnt_node;
ss.push(u);
for(int i = e1.head[u]; i; i = e1.nxt[i])
{
int v = e1.to[i];
if(!dfn[v])
{
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(!id[v])
{
low[u] = min(low[u], dfn[v]);
}
}
if(dfn[u] == low[u])
{
cntn++;
while(1)
{
int now = ss.top();
ss.pop();
id[now] = cntn;
if(now == u) break;
}
}
}
int xp[100007], yp[100007];
int flagg;
void dfs(int u, int fa, int en)
{
if(flagg) return;
if(u == en)
{
flagg = 1;
return;
}
for(int i = e2.head[u]; i; i = e2.nxt[i])
{
int v = e2.to[i];
if(v == fa) continue;
dfs(v, u, en);
}
}
signed main()
{
scanf("%d%d%d%d", &n, &m, &k, &q);
for(int i = 1; i <= n; ++i)
{
scanf("%s", s);
for(int j = 0, len = strlen(s); j < len; ++j)
if(s[j] == '.') mp[(i - 1) * m + j + 1] = 1;
else mp[(i - 1) * m + j + 1] = 0;
}
for(int i = 1; i <= n * m; ++i)
{
if(!mp[i]) continue;
int now = i, lie = (i - (i / m) * m == 0 ? m : i - (i / m) * m), hang = i / m + (i % m == 0 ? 0 : 1);
if(hang != 1 && mp[i - m])
e1.add(now, i - m);
if(hang != n && mp[i + m])
e1.add(now, i + m);
if(lie != 1 && mp[i - 1])
e1.add(now, i - 1);
if(lie != m && mp[i + 1])
e1.add(now, i + 1);
}
for(int i = 1; i <= k; ++i)
{
xp[i] = (read() - 1) * m + read(), yp[i] = (read() - 1) * m + read();
e1.add(xp[i], yp[i]);
}
for(int i = 1; i <= n * m; ++i)
if(mp[i] && !dfn[i]) tarjan(i);
for(int i = 1; i <= k; ++i)
if(id[xp[i]] != id[yp[i]]) e2.add(id[xp[i]], id[yp[i]]);
for(int i = 1; i <= q; ++i)
{
int p1 = (read() - 1) * m + read(), p2 = (read() - 1) * m + read();
flagg = 0;
dfs(id[p1], 0, id[p2]);
if(flagg)
puts("1");
else
puts("0");
}
return 0;
}