题面
【题目描述】
某军搞信息对抗实战演习,红军成功地侵入了蓝军的内部网络,蓝军共有两个信息中心,红军计划在某台中间服务器上安装一个嗅探器,从而能够侦听到两个信息中心互相交换的所有信息,但是蓝军的网络相当的庞大,数据包从一个信息中心传到另一个信息中心可以不止有一条通路。现在需要你尽快地解决这个问题,应该把嗅探器安装在哪个中间服务器上才能保证所有的数据包都能被捕获?
【输入】
输入文件的第一行一个整数 n,表示蓝军网络中服务器的数目。1<=n<=100
接下来若干行是对蓝军网络的拓扑结构描述,每行是两个整数 i , j 表示编号为 i 和编号为 j 的两台服务器间存在连接(显然连接是双向的),服务器的编号从 1 开始,一行两个 0 表示网络的拓补结构描述结束,再接下来是两个整数 a , b 分别表示两个中心服务器的编号。
【输出】
输出编号。如果有多个解输出编号最小的一个,如果找不到任何解,输出 No solution
【样例输入】
5
2 1
2 5
1 4
5 3
2 3
5 1
0 0
4 2
【样例输出】
1
算法分析
通过题面可以知道,我们需要求解割点。同时,两个中心服务器进行信息传递,那么可以以其中一个中心服务器为起点进行tarjan搜索。
但是,并不是所有割点都可以,如下图两种情况:
假设两个中心服务器为
1
、
3
1、3
1、3。
(1)
3
3
3是割点,但是,这种情况无解。
(2)不通过割点就可以进行传送,割点2是无用的。
因此,割点需要满足以下要求:
(1)割点不是中心服务器
(2)如果中心服务器是
u
,
v
u,v
u,v,割点为
x
x
x,以
u
u
u为起点进行访问,需要满足:
d
f
n
[
x
]
<
=
l
o
w
[
v
]
dfn[x]<=low[v]
dfn[x]<=low[v]。
v
v
v必须在割点
x
x
x之后访问,且
v
v
v不能越过割点
x
x
x访问之前的点。
参考程序
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int a,b,n,ans,timee,root,low[110],dfn[110],cnt[110];
int fist[10100],to[10100],nex[10100],t;
void add(int x,int y)
{
to[++t]=y;
nex[t]=fist[x];
fist[x]=t;
return;
}
void tarjin(int u,int dad)
{
low[u]=dfn[u]=++timee;
int v;
for(int i=fist[u];i!=-1;i=nex[i])
{
v=to[i];
if(!dfn[v]) //未访问
{
tarjin(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]) //是割点
{
if(u!=a&&u!=b)
{
if(dfn[u]<=low[b]) //b在u点之后访问,且不能访问到u之前的结点
ans=min(ans,u);
}
}
}
else if(v!=dad)
low[u]=min(low[u],dfn[v]);
}
return ;
}
int main()
{
memset(fist,-1,sizeof(fist));
scanf("%d",&n);
while(1)
{
scanf("%d%d",&a,&b);
if(a==0&&b==0) break;
add(a,b);
add(b,a);
}
scanf("%d%d",&a,&b);
ans=n+1;
tarjin(a,a); //以其中一个中心服务器为起点
if(ans>n) printf("No solution\n");
else printf("%d\n",ans);
return 0;
}