题目链接:https://www.luogu.com.cn/problem/P5058
思路:这个题其实想明白了就是一个很裸的找tarjan割点,但是这个割点的范围在(a,b)之间,即不包括a和b,所以我们可以考虑dfn,以a作为root点跑tarjan,然后判断是不是割点,再在割点的基础上判(dfn[v]是否小于等于dfn[b],因为是个回溯的过程嘛,如果b赋上了dfn的值,那么i肯定也有,如果b没附上,那i即使大于b且i是割点,那我们也不把他当成真割点)。最后rep(i,1,n)看一下最小的真割点是谁
ps:这里我提一下为啥判的时候dfn[v]=dfn[b]的情况,emm这个情况其实就是这个割点x刚好在b前面那个点啦!注意对象是x!!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl ' ' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=5e5+5; int tot,head[maxn]; struct E{ int to,next; }edge[maxn<<1]; void add(int u,int v){ edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } int a,b; int id[maxn],dfn[maxn],low[maxn],tott,cnt; stack<int> s;int fa[maxn],cut[maxn]; vector<int> bccs[maxn]; void tarjan(int x){ low[x]=dfn[x]=++tott; s.push(x);int son=0; for(int i=head[x];i!=-1;i=edge[i].next){ int v=edge[i].to; if(!dfn[v]){ ++son;fa[v]=x; tarjan(v); low[x]=min(low[x],low[v]); if(low[v]>=dfn[x]){ if(dfn[v]<=dfn[b])cut[x]=true; ++cnt; bccs[cnt].clear(); while(1){ int now=s.top();s.pop(); id[now]=cnt; bccs[cnt].push_back(now); if(now==v) break; } id[x]=cnt; bccs[cnt].push_back(x); } } else if(v!=fa[x]) low[x]=min(low[x],dfn[v]); } if(fa[x]==-1&&son==1) cut[x]=false; } int m,n; int main(){ cin>>n; int u,v;mem(head,-1); while(cin>>u>>v&&u){ add(u,v);add(v,u); } cin>>a>>b; tarjan(a); rep(i,1,n){ if(i!=a&&cut[i]){ cout<<i<<endl;return 0; } } puts("No solution"); }