#割点,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");
}
posted @ 2020-11-03 20:54  lemondinosaur  阅读(43)  评论(0编辑  收藏  举报