【题解】[ ZJOI 2004] 嗅探器

题面

【题目描述】
某军搞信息对抗实战演习,红军成功地侵入了蓝军的内部网络,蓝军共有两个信息中心,红军计划在某台中间服务器上安装一个嗅探器,从而能够侦听到两个信息中心互相交换的所有信息,但是蓝军的网络相当的庞大,数据包从一个信息中心传到另一个信息中心可以不止有一条通路。现在需要你尽快地解决这个问题,应该把嗅探器安装在哪个中间服务器上才能保证所有的数据包都能被捕获?
【输入】
输入文件的第一行一个整数 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 13
(1) 3 3 3是割点,但是,这种情况无解。
在这里插入图片描述
(2)不通过割点就可以进行传送,割点2是无用的。
在这里插入图片描述
因此,割点需要满足以下要求:
(1)割点不是中心服务器
(2)如果中心服务器是 u , v u,v uv,割点为 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值