我用的方法和题解不太一样,直接用了一个vis数组,代表是否能从该点访问到终点,并且tarjan从源点开始跑的。判据是这个点存在子节点导致割点形成,并且子该节点能够访问到终点。
//g++ -g b.cpp -o b -std=c++14 -O2 -Wall
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=2e5+10;
int N,M,head[maxn],dfn[maxn],low[maxn],nume=0,Tm=0,ans=maxn,vis[maxn],S,T;
struct node{int to,nxt;}e[maxn<<3];
int qd(){
int rt=0;char c=getchar();
while(c<'0'||c>'9') c=getchar();
while('0'<=c&&c<='9') rt=(rt<<3)+(rt<<1)+c-48,c=getchar();
return rt;
}
void edgen(int from,int to){
e[++nume].nxt=head[from];
head[from]=nume;
e[nume].to=to;
}
void dfs(int fa,int u){
// printf("dfs %d %d\n",fa,u);
dfn[u]=low[u]=++Tm;int flag=0;
if(u==T) vis[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!dfn[v]){
dfs(u,v);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]&&vis[v]) flag=1;
}
else low[u]=min(low[u],dfn[v]);
if(v!=fa) vis[u]|=vis[v];
}
if(flag&&u!=S&&u!=T) ans=min(ans,u);
// printf("%d:dfn=%d,low=%d flag=%d vis=%d\n",u,dfn[u],low[u],flag,vis[u]);
}
int main(){
// freopen("in.txt","r",stdin);
N=qd();
for(;1;M++){
int x=qd(),y=qd();
if(x+y==0) break;
edgen(x,y),edgen(y,x);
}
S=qd(),T=qd();
dfs(0,S);
if(ans==maxn) printf("No solution\n");
else printf("%d\n",ans);
return 0;
}