#割点,Tarjan#洛谷 5058 [ZJOI2004]嗅探器
题目
询问能编号最小的割点删掉后使\(a\)和\(b\)无法连通
分析
考虑将\(a\)当作根,那么割点的dfn小于等于\(b\)的dfn就可以了,
怎么会呢,如果有一个环呢,所以得要让割点的子节点小于等于\(b\)的dfn才可以
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=200011;
struct node{int y,next;}e[500011];
int as[N],dfn[N],low[N],cut[N],et=1,A,n,m,tot,root;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline signed min(int a,int b){return a<b?a:b;}
inline void tarjan(int x,int F){
dfn[x]=low[x]=++tot; rr int sub=0;
for (rr int i=as[x];i;i=e[i].next)
if (!dfn[e[i].y]){
tarjan(e[i].y,i^1);
low[x]=min(low[x],low[e[i].y]);
if (dfn[x]<=low[e[i].y]){
++sub;
if (x!=root||sub>1){
if (dfn[e[i].y]<=dfn[A]) cut[x]=1;
}
}
}else if (i!=F) low[x]=min(low[x],dfn[e[i].y]);
}
signed main(){
n=iut();
while (1){
rr int x=iut(),y=iut();
if (!x&&!y) break;
e[++et]=(node){y,as[x]},as[x]=et,
e[++et]=(node){x,as[y]},as[y]=et;
}
root=iut(),A=iut(),tarjan(root,0);
for (rr int i=1;i<=n;++i)
if (cut[i]) return !printf("%d",i);
return !printf("No solution");
}