F.Fief
结论题:
首先整张图需要是联通的
对原图找割点,点双缩点
若不存在割点,意味着都是YES
建立新图统计每一个点双的度数
当且仅当缩点后的图为一条链且u和v都在首尾度数为1的点双中才是YES
否则NO
const int N = 200010, M = 400010;
int n, m, k, timestamp, top, idx, dcc_cnt, ans, root,id[N];
int e[M], ne[M], h[N], stk[M], dfn[N], low[N], deg[N],d[M],from[N];
bool ins[M], is_bridge[M],cut[N];
vector<int> dcc[N];
void add(int a,int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void tarjan(int u){
dfn[u] = low[u] = ++timestamp;
stk[++ top] = u;
if(u == root && h[u] == -1){
//孤立点
dcc_cnt ++;
dcc[dcc_cnt].push_back(u);
return ;
}
int cnt = 0;
for(int i=h[u];~i;i=ne[i]){
int j = e[i];
if(!dfn[j]){
tarjan(j);
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 --];
id[y] = dcc_cnt;
dcc[dcc_cnt].push_back(y);
}while(y!=j);
dcc[dcc_cnt].push_back(u);
}
}
else low[u] = min(low[u], dfn[j]);
}
}
vector<int> edge[N];
int fa[N];
int find(int x){
return fa[x]==x?fa[x]:fa[x]=find(fa[x]);
}
void solve(){
n=read(),m=read();
rep(i,1,n) fa[i]=i;
rep(i,1,m){
int u=read(),v=read();
add(u, v), add(v, u);
int pu=find(u),pv=find(v);
if(pu!=pv) fa[pu]=pv;
}
for(root=1;root<=n;++root)
if(!dfn[root])
tarjan(root);
int tmp=0;
bool connec = true;
for(int i=1;i<=n;++i)
if(find(i)==i) tmp ++;
if(tmp>1) connec=false;
bool NO = 0, YES = 1;
for(int i=1;i<=n;++i)
if(cut[i]) {
YES=0; break;}
int num=dcc_cnt;
for(int i=1;i<=dcc_cnt;++i) {
for(auto u:dcc[i]){
if(cut[u]) {
if(!from[u]) from[u]=++num;
edge[from[u]].push_back(i);
edge[i].push_back(from[u]);
d[i] ++;
d[from[u]] ++;
if(d[i]>=3||d[from[u]]>=3) NO = 1;
}
else from[u]=i;
}
}
int q=read();
while(q--){
int u=read(),v=read();
if(!connec||NO) puts("NO");
else if(YES) puts("YES");
else if(d[from[u]]==1&&d[from[v]]==1&&from[u]!=from[v]) puts("YES");
else puts("NO");
}
}