问题 B(1452): 嗅探器
时间限制: 1 Sec
内存限制: 64 MB
题目描述
某军搞信息对抗实战演习.红军成功地侵入了蓝军的内部网络.蓝军共有两个信息中心.红军计划在某台中间服务器上安装一个嗅探器,从而能够侦听到两个信息中心互相交换的所有信息.但是蓝军的网络相当的庞大,数据包从一个信息中心传到另一个信息中心可以不止有一条通路.现在需要你尽快地解决这个问题.应该把嗅探器安装在哪个中间服务器上才能保证所有的数据包都能被捕获?
输入
输入包含多个测试数据 第一行一个整数n(1<=n<=100),表示蓝军网络中服务器的数目. 接下来若干行是对蓝军网络的拓扑结构描述.每行是两个整数i,j表示编号为I和编号为j的两台服务器间存在连接(显然连接是双向的).服务器的编号从1开始.描述以两个0结束. 再接下来一行是两个整数a,b分别表示两个中心服务器的编号.
输出
第1行:一个整数,表示嗅探器安装在哪个中间服务器上的编号,如果有多个解输出编号最小的一个.如果找不到任何解,输出”No solution”.
样例输入
5
2 1
2 5
1 4
5 3
2 3
5 1
0 0
4 2
样例输出
1
【解析】
这道题就是一道割点与割边的题目,虽然不是板题,但至少也用到了那样的思路。首先我们可以枚举那一个点,然后将其他的边相连,后再判断那两个指挥中心是否在同一个集合里,是则舍去,反之输出答案。至于在判断的时候,我们则可以用并查集来实现。
【代码】
#include <cstdio>
#include <cstring>
#include <string>
bool hash[110][110]; //判重边
long fa[110];
struct Edge
{
long u;
long v;
};
Edge edge[10010];
long cedge = 0;
long getroot(long a)
{
if (fa[a] == a)
return fa[a];
return fa[a] = getroot(fa[a]);
}
void merge(long a,long b)
{
fa[getroot(a)] = getroot(b);
}
long getint()//读入优化
{
long rs=0;bool sgn=1;char tmp;
do tmp=getchar();
while (!isdigit(tmp)&&tmp-'-');
if (tmp=='-'){tmp=getchar();sgn=0;}
do rs=(rs<<3)+(rs<<1)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
int main()
{
long n = getint();
while (1)
{
long u = getint();
long v = getint();
if (u == 0 && v == 0)
break;
if (hash[u][v]) continue;
hash[u][v]=hash[v][u]=true;
++cedge;
edge[cedge].u = u;
edge[cedge].v = v;
}
long s = getint();
long t = getint();
for (long p=1;p<n+1;p++)
{
if (p == s || p == t) continue;
for (long i=1;i<n+1;i++)
fa[i] = i;
for (long i=1;i<cedge+1;i++)
if (edge[i].u!=p && edge[i].v!=p)
merge(edge[i].u,edge[i].v);
if (getroot(s) != getroot(t))
{
printf("%ld",p);
return 0;
}
}
printf("No solution");
return 0;
}