当时看到这道题目有点想法后来看到59交0AC, 就知道肯定有不少trick,赛后看了题解才知道原来有这么多种情况。。。
其实所有的情况大致可以这么划分, u 和 v是否相同, u, v不同时, 设u所在环是cu, v所在环是cv, p所在环是cp, 根据
cu == cv再划分出两种cu != cv时再根据cu == cp || cp == cv再划分出两种情况, 基本就是这样, 对于最后几种情况
还有考虑出环的点和入环的点这个可以在dfs的过程中得到, 代码很长很丑。。。。
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <ctime>
#include <algorithm>
using namespace std;
inline int readint() {
char c = getchar();
while (!isdigit(c)) c = getchar();
int x = 0;
while (isdigit(c)) {
x = x * 10 + c - '0';
c = getchar();
}
return x;
}
const int N = 100005;
const int M = N << 2;
const int lim = 17; // 2 ^ lim > N
int in[N], out[N];
struct Tree {
struct Edge {
int v, ou, ov;
Edge* next;
void init(int a, Edge* e, int b, int c) {
v = a, ou = b, ov = c;
next = e;
}
};
Edge E[M];
Edge* it, * head[N];
int pa[N][lim], dep[N], dis[N];
bool vis[N];
int n;
void init(int n) {
this->n = n;
for (int i = 0; i < n; i++) {
head[i] = 0, vis[i] = 0;
}
it = E;
}
void add(int u, int v, int ou, int ov) {
it->init(v, head[u], ou, ov);
head[u] = it++;
it->init(u, head[v], ov, ou);
head[v] = it++;
}
int lca(int u, int v) {
if (dep[u] > dep[v]) swap(u, v);
if (dep[u] < dep[v]) {
int d = dep[v] - dep[u];
for (int i = 0; i < lim; i++)
if (d & (1 << i))
v = pa[v][i];
}
if (u != v) {
for (int i = lim - 1; i >= 0; i--)
if (pa[u][i] != pa[v][i]) {
u = pa[u][i];
v = pa[v][i];
}
u = pa[u][0];
}
return u;
}
void dfs(int u, int fa) {
pa[u][0] = fa;
dep[u] = dep[fa] + 1;
vis[u] = 1;
for (int i = 1; (1 << i) < n; i++)
pa[u][i] = pa[pa[u][i - 1]][i - 1];
for (Edge* e = head[u]; e; e = e->next) {
int v = e->v;
if (!vis[v] && v != fa) {
out[v] = e->ov, in[v] = e->ou;
dfs(v, u);
}
}
}
int anc(int u, int d) {
if (d < 0) return -1;
if (d == 0) return u;
int fa = u;
for (int i = 0; (1 << i) < n; i++) {
if (d & (1 << i)) {
fa = pa[u][i];
u = fa;
}
}
return fa;
}
void run(int rt) {
dep[rt] = -1;
dfs(rt, rt);
}
}T;
struct Graph {
struct Edge {
int v;
bool iscut;
Edge* next, * pair;
void init(int a, Edge* e1, Edge* e2) {
this->v = a, next = e1;
pair = e2;
iscut = 0;
}
};
Edge E[M], * head[N];
int pre[N], low[N], no[N];
Edge* it;
int n, id, tdfn;
void init(int n) {
this->n = n;
for (int i = 0; i < n; i++) {
head[i] = 0;
pre[i] = 0;
}
it = E;
tdfn = 1;
}
void add(int u, int v) {
it->init(v, head[u], it + 1);
head[u] = it++;
it->init(u, head[v], it - 1);
head[v] = it++;
}
int dfs(int u, int fa) {
int lowu = pre[u] = tdfn++;
for (Edge* e = head[u]; e; e = e->next) {
int v = e->v;
if (!pre[v]) {
int lowv = dfs(v, u);
lowu = min(lowv, lowu);
if (lowv > pre[u]) {
e->iscut = 1;
e->pair->iscut = 1;
}
}
else if(v != fa && pre[v] < pre[u]) {
lowu = min(lowu, pre[v]);
}
}
low[u] = lowu;
return lowu;
}
void dfs(int u) {
no[u] = id;
for (Edge* e = head[u]; e; e = e->next) {
if (e->iscut) continue;
int v = e->v;
if (no[v] == -1)
dfs(v);
}
}
void run() {
dfs(0, -1);
id = 0;
for (int i = 0; i < n; i++) no[i] = -1;
for (int i = 0; i < n; i++)
if (no[i] == -1) {
dfs(i);
id++;
}
T.init(id);
for (int u = 0; u < n; u++)
for (Edge* e = head[u]; e; e = e->next) {
int v = e->v;
if (no[u] != no[v])
T.add(no[u], no[v], u, v);
}
T.run(0);
}
bool gao(int u, int v, int p) {
if (u == v) {
if (p == u) return 1;
else return 0;
}
else {
int tu = no[u], tv = no[v];
int tp = no[p];
if (tu == tv) {
if (tp != tu) return 0;
else return 1;
}
else {
int fa = T.lca(tu, tv);
if (tu == tp || tp == tv) {
if (tu == tp) {
if (fa != tu) {
if (p != u && out[tu] == u)
return 0;
else
return 1;
}
else {
int d = T.dep[tv] - T.dep[tu];
int su = T.anc(tv, d - 1);
if (p != u && in[su] == u)
return 0;
else
return 1;
}
}
else {
if (fa != tv) {
if (p != v && out[tv] == v)
return 0;
else
return 1;
}
else {
int d = T.dep[tu] - T.dep[tv];
int fu = T.anc(tu, d - 1);
if (p != v && in[fu] == v)
return 0;
else
return 1;
}
}
}
else {
int du = T.dep[tu] - T.dep[tp], dv = T.dep[tv] - T.dep[tp];
int t1 = T.anc(tu, du - 1), t2 = T.anc(tv, dv - 1);
if ((T.dep[tp] >= T.dep[fa]) &&
((du > 0 && T.pa[t1][0] == tp) || (dv > 0 && T.pa[t2][0] == tp))) {
if (tp == fa) {
if (in[t1] == in[t2] && in[t1] != p)
return 0;
else
return 1;
}
else {
if (T.pa[t1][0] == tp) {
if (out[tp] == in[t1] && out[tp] != p)
return 0;
else
return 1;
}
else {
if (out[tp] == in[t2] && out[tp] != p)
return 0;
else
return 1;
}
}
}
else {
return 0;
}
}
}
}
}
}G;
int main() {
int n, m, q, u, v, p;
while (~scanf("%d", &n)) {
m = readint();
G.init(n);
for (int i = 0; i < m; i++) {
u = readint(), v = readint();
u--, v--;
G.add(u, v);
}
G.run();
q = readint();
for (int i = 0; i < q; i++) {
u = readint(), v = readint(), p = readint();
u--, v--, p--;
if (G.gao(u, v, p))
puts("Yes");
else
puts("No");
}
}
return 0;
}