题解 P5058 [ZJOI2004]嗅探器

一道 \(tarjan\)

蓝军共有两个信息中心,红军计划在某台中间服务器上安装一个嗅探器,从而能够侦听到两个信息中心互相交换的所有信息。

也就是说,\(a\)\(b\) 的所有路径必须经过 那个中间服务器。

-----> 如果删去那个中间服务器,\(a\)\(b\) 不联通。

-----> 那个中间服务器是一个割点。(一个特殊的割点)

假设用 \(now\) 表示当前结点, \(v\) 表示儿子。

\(exa[now]\) 表示当前结点所在子树中有无 \(a\)

\(exb[now]\) 同理

那么当且仅当以下条件全部发生时,\(now\) 可以更新 \(ans\)

  • now为割点(这是显然的,上面已分析)
  • 在以上条件成立时,\(a\)\(b\) 只能有一个在 \(v\) 的子树内(因为删去 \(now\)\(v\) 的子树的点与其他点不联通)(如果a,b都不在v内,now也可能是答案,但这是通过其他子树来实现的)。
  • now!=a&&now!=b(一定不要忘记)(看清题目)

Code

#include<cstdio>
#include<iostream>
#define LL long long
#define rint register int
using namespace std;
namespace FastIO
{
char c;
bool sign;
template<class T>
inline void read(T &x)
{
	x=0;
	sign=false;
	for(c=getchar();c<'0'||c>'9';c=getchar()) 
		if(c=='-') 
			sign=true;
	for(;c>='0'&&c<='9';c=getchar()) 
		x=(x<<1)+(x<<3)+(c&15);
	if(sign) x=~x+1;
	return;
}
}
using FastIO::read;
//======================================
const int N=2e5+5;
const int M=1e6+5;
int one[N];
int ver[M],Next[M];
int tot=0;
inline void AddEdge(const int &a,const int &b)
{
	tot++;
	Next[tot]=one[a];
	one[a]=tot;
	ver[tot]=b;
	return;
}
//======================================
int n;
int a,b;
int dfn[N],low[N],times=0;
bool exa[N],exb[N]; // 在搜索树的子树中有没有 a,b
int ans=N+3;
void tarjan(int now,const int &fa)
{
	dfn[now]=low[now]=++times;
	rint i,v,child=0;
	for(i=one[now];i>0;i=Next[i]) {
		v=ver[i];
		if(!dfn[v]) {
			child++;
			tarjan(v,now);
			low[now]=min(low[now],low[v]);
			if(exa[v]) exa[now]=true;
			if(exb[v]) exb[now]=true; 
			if((fa==-1&&child>1)||(fa!=-1&&low[v]>=dfn[now]))
				if(exa[v]^exb[v]&&now!=a&&now!=b) // !!!
					ans=min(ans,now);
		}
		else if(v!=fa) 
			low[now]=min(low[now],dfn[v]);
	}
	return;
} 
int main()
{
//	freopen("1.in","r",stdin);
	rint i;
	int x,y;
	read(n);
	while(true) {
		read(x); read(y);
		if(x==0&&y==0) 
			break;
		AddEdge(x,y);
		AddEdge(y,x);
	}
	read(a); read(b);
	exa[a]=true;
	exb[b]=true;
//	tarjan(a,-1);
	for(i=1;i<=n;i++) 
		if(dfn[i]==0) 
			tarjan(i,-1);
	if(ans==N+3) 
		puts("No solution");
	else printf("%d\n",ans);
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/cjl-world/p/13168492.html
今日推荐