合法的几种情况:
1、只有两个点
2、缩完点后只有一个点双连通分量
3、缩完点后是一条链,两个点不是割点并且分别位于链的两端
wa了好几发的原因:判断缩完点之后是否为一条链,既要满足每个连通分量内的割点数量<3,也要满足每个割点所处连通分量的个数<3(可以手动模拟一下,发现对应两种不同的情况)
#include<bits/stdc++.h>
using namespace std;
#define fr first
#define se second
#define et0 exit(0);
#define rep(i, a, b) for(int i = (int)(a); i <= (int)(b); i ++)
#define rrep(i, a, b) for(int i = (int)(a); i >= (int)(b); i --)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef unsigned long long ULL;
const int INF = 0X3f3f3f3f, N = 1e5 + 10, M = 4e5 + 10, MOD = 1e9 + 7;
const double eps = 1e-7, pi = acos(-1);
int n, m;
int st[N], st_cnt;
int cut_cnt[N];
int head[N], idx;
struct EGDE {
int to, next;
} eg[M];
void add(int x, int y) {
eg[idx].to = y;
eg[idx].next = head[x];
head[x] = idx++;
}
int dfn[N], low[N], timestamp;
int stk[N], top;
int dcc_cnt;
vector<int> dcc[N];
bool cut[N];
void tarjan(int u, int root) {
dfn[u] = low[u] = ++ timestamp;
stk[ ++ top] = u;
if (u == root && head[u] == -1) {
dcc_cnt ++ ;
dcc[dcc_cnt].push_back(u);
return;
}
int cnt = 0;
for (int i = head[u]; ~i; i = eg[i].next) {
int j = eg[i].to;
if (!dfn[j]) {
tarjan(j, root);
low[u] = min(low[u], low[j]);
if (dfn[u] <= low[j]) {
cnt ++ ;
if (u != root || cnt > 1) cut[u] = true;
++ dcc_cnt;
int y;
do {
y = stk[top -- ];
dcc[dcc_cnt].push_back(y);
} while (y != j);
dcc[dcc_cnt].push_back(u);
}
} else low[u] = min(low[u], dfn[j]);
}
}
void work() {
memset(head, -1, sizeof head);
cin >> n >> m;
rep(i, 1, m) {
int x, y;
cin >> x >> y;
add(x, y);
add(y, x);
}
int q;
cin >> q;
if (n == 2) {
while (q--) cout << "YES" << endl;
return;
}
int k = 0;
rep(i, 1, n)
if (!dfn[i]) k++, tarjan(i, i);
if (k > 1) {
while (q--) cout << "NO" << endl;
return;
}
rep(i, 1, dcc_cnt) {
k = 0;
rep(j, 0, dcc[i].size() - 1)
if (cut[dcc[i][j]]) k++, cut_cnt[dcc[i][j]]++;
if (k >= 3) {
while (q--) cout << "NO" << endl;
return;
} else if (k == 1) {
st_cnt++;
rep(j, 0, dcc[i].size() - 1)
if (!cut[dcc[i][j]]) st[dcc[i][j]] = st_cnt;
}
}
rep(i, 1, n)
if (cut[i] && cut_cnt[i] >= 3) {
while (q--) cout << "NO" << endl;
return;
}
//到这里肯定是一条链
while (q--) {
int x, y;
cin >> x >> y;
if (dcc_cnt == 1) cout << "YES" << endl;
else if (st[x] && st[y] && st[x] != st[y]) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
signed main() {
IO
int test = 1;
// cin >> test;
while (test--) {
work();
}
return 0;
}