看了看题解,不太明白,于是口胡想出了下面的做法,得到 AC。
先把所有的不在任何一条 a 到 b 的简单路径上的点筛出来,扔掉,然后直接求割点。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,a,b,fi[200010],vis[200010],ans=1e9;
int l[200010],d[200010],s[200010],ct[200010],c,r;
vector<int> e[200010],k[200010];
void dfs(int u){
if(u==b) return ;
vis[u]=1;
for(int i=0;i<int(e[u].size());i++){
int v=e[u][i];
if(!vis[v]){
dfs(v);
fi[u]=max(fi[u],fi[v]);
}
}
}
void tarj(int u){
l[u]=d[u]=++c;
int son=0;
for(int i=0;i<int(k[u].size());i++){
int v=k[u][i];
if(!d[v]){
son++;
tarj(v);
l[u]=min(l[u],l[v]);
if(l[v]>=d[u]&&u!=r) ct[u]=1;
}
else l[u]=min(l[u],d[v]);
}
if(u==r&&son>=2) ct[u]=1;
}
int main(){
scanf("%d",&n);
while(1){
scanf("%d%d",&a,&b);
if(a==0&&b==0) break;
e[a].push_back(b);
e[b].push_back(a);
}
scanf("%d%d",&a,&b);
fi[b]=1;
dfs(a);
for(int i=1;i<=n;i++){
for(int j=0;j<int(e[i].size());j++){
int v=e[i][j];
if(fi[i]==fi[v]&&fi[i]==1) k[i].push_back(v);
}
}
for(int i=1;i<=n;i++){
if(!d[i]&&fi[i]){
r=i;
tarj(i);
}
}
for(int i=1;i<=n;i++){
if(ct[i]&&i!=a&&i!=b) ans=min(i,ans);
}
if(ans==int(1e9)) printf("No solution");
else printf("%d",ans);
}