题目描述
Freda是一个迷宫爱好者,她利用业余时间建造了许多迷宫。每个迷宫都是由若干房间和走廊构成的,每条走廊都连接着两个不同的房间,两个房间之间最多只有一条走廊直接相连,走廊都是双向通过。
黄昏时候,Freda喜欢在迷宫当中漫步。每天,Resodo都会为Freda设计一个挑战方案。Resodo会指定起点和终点,请Freda来找到一条从起点到终点的简单路径。一条简单路径定义为一个房间序列,每个房间至多在序列里出现一次,且序列中相邻的两个房间有走廊相连。当起点和终点之间存在且仅存在一条简单路径的时候,Freda认为这个挑战方案是RD的。现在,请你帮帮Resodo来写一个程序,判断一个挑战方案是否是RD的。
输入格式
第一行三个整数N,M,Q.分别表示房间数,走廊数,询问数。
接下来M行每行2个整数x,y, 0<x,y<=N, 表示x和y之间有一条走廊相连。
接下来Q行每行2个整数x,y, 表示询问以x为起点,y为终点的挑战方案是否是RD的.
输出格式
对于每个询问,输出一行”Y”或者”N”(不含引号).Y表示该询问所表示的挑战方案是RD的,N表示该询问所表示的挑战方案不是RD的.
样例输入
6 5 3
1 2
2 3
2 4
2 5
4 5
1 3
1 5
2 6
样例输出
Y
N
N
样例解释
1,3之间只有一条路径 1->2->3
1,5之间有两条路径 1->2->5 ; 1->2->4->5
1,6之间没有路径
数据范围与约定
对于30%的数据,N<=100, M<=1000, Q<=100.
对于50%的数据,N<=1000, M<=10000, Q<=1000.
对于100%的数据,N<=10000, M<=100000, Q<=10000.
Solution
感觉好久没写割边系列的题了,现在板子都不会打了。(我好菜啊)
我们发现如果连接\(u\)与\(v\)的简单路径上的边不是桥的话,就一定会有另外的路径也可以联通\(u\)和\(v\)。
我们求出所有的桥,并将联通的桥所涉及的点做一个并查集。最后就可以直接查询了。
#include <queue>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int N = 10002, M = 100002;
int f[N], tot, dfn[N], low[N], cnt, n, m, Q, head[N], dot[M << 1], nxt[M << 1];
int read() {
int x = 0, f = 1; char S;
while((S = getchar()) > '9' || S < '0') {
if(S == '-') f = -1;
if(S == EOF) exit(0);
}
while(S <= '9' && S >= '0') {
x = (x << 1) + (x << 3) + (S ^ 48);
S = getchar();
}
return x * f;
}
void addEdge(const int u, const int v) {
dot[++ cnt] = v;
nxt[cnt] = head[u];
head[u] = cnt;
}
int findSet(const int x) {
return x == f[x] ? x : f[x] = findSet(f[x]);
}
void unionSet(const int u, const int v) {
int x = findSet(u), y = findSet(v);
if(x != y) f[x] = y;
}
void makeSet() {
for(int i = 1; i <= n; ++ i) f[i] = i;
}
void tarjan(const int u, const int ba) {
dfn[u] = low[u] = ++ tot;
for(int i = head[u]; i; i = nxt[i]) {
int v = dot[i];
if(v == ba) continue;
if(dfn[v]) low[u] = min(low[u], dfn[v]);
else {
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(low[v] > dfn[u]) unionSet(u, v);
}
}
}
int main() {
int a, b;
n = read(), m = read(), Q = read();
makeSet();
for(int i = 1; i <= m; ++ i) {
a = read(), b = read();
addEdge(a, b), addEdge(b, a);
}
tarjan(1, 0);
while(Q --) {
a = read(), b = read();
if(findSet(a) == findSet(b)) puts("Y");
else puts("N");
}
return 0;
}