题目链接:传送门
思路:求A到B之间必要的中间节点
条件:(1)只有一条路径经过中间节点;(low[B]>=num[u]&&num[v]<=num[B],没有从B到u的路径)
(2)中间节点不能和A,B重合(u!=A&&num[v]<=num[B],先v后B)
(3)中间节点一定是割点(num[u]<=low[v])
然后就是Tarjan的模板了。
参考文章:传送门

#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int maxn = 100100; int num[maxn],vis[maxn],low[maxn],tim,A,B,ans; vector <int> vc[maxn]; void Init() { memset(num,0,sizeof(num)); memset(vis,0,sizeof(vis)); memset(low,0,sizeof(low)); tim=0;ans=9999999; } void Tarjan(int u,int pre) { num[u]=low[u]=++tim; int i,v; for(i=0;i<vc[u].size();i++){ v=vc[u][i]; if(!num[v]){ Tarjan(v,u); low[u]=min(low[u],low[v]); if(u!=A&&num[u]<=low[v]&&num[v]<=num[B]&&low[B]>=num[u]) ans=min(ans,u); } else if(pre!=v) low[u]=min(low[u],num[v]); } } int main(void) { int n,m,i,j,x,y; while(~scanf("%d",&n)){ Init(); while(scanf("%d%d",&x,&y)&&(x+y)){ vc[x].push_back(y); vc[y].push_back(x); } scanf("%d%d",&A,&B); Tarjan(A,-1); if(ans<=n) printf("%d ",ans); else printf("No solution "); } return 0; }