[ZJOI2004]嗅探器

洛咕

题意:某军搞信息对抗实战演习,红军成功地侵入了蓝军的内部网络,蓝军共有两个信息中心,红军计划在某台中间服务器上安装一个嗅探器,从而能够侦听到两个信息中心互相交换的所有信息,但是蓝军的网络相当的庞大,数据包从一个信息中心传到另一个信息中心可以不止有一条通路。现在需要你尽快地解决这个问题,应该把嗅探器安装在哪个中间服务器上才能保证所有的数据包都能被捕获?

一句话题意:给定\(n(n<=100)\)个点的无向图和两个特殊点,删掉一个点后使得两个特殊点不连通,试求这个点.

分析:这道题的数据范围真的是小的可爱,如果大一点应该会是道好题.

直接tarjan求出所有的缩点,然后枚举所有缩点,重新建图(把所有与该缩点有关的边忽略),然后暴力从其中一个特殊点开始跑dfs,如果搜到了另一个特殊点,则该割点不合法,否则直接输出就好了.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=105;
const int M=10005;
int a[M],b[M],visit[N];
int tot,head[N],nxt[M],to[M];
int top,root,timeclock,dfn[N],low[N],cut[N];
inline void add(int a,int b){
	nxt[++tot]=head[a];head[a]=tot;to[tot]=b;
}
inline void tarjan(int u){
	dfn[u]=low[u]=++timeclock;
	int child=0;
	for(int i=head[u];i;i=nxt[i]){
		int v=to[i];
		if(!dfn[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u]){
				++child;
				if(u!=root||child>=2)cut[u]=1;
			}
		}
		else low[u]=min(low[u],dfn[v]);
	}
}
inline bool dfs(int u,int goal){
	visit[u]=1;
	for(int i=head[u];i;i=nxt[i]){
		int v=to[i];
		if(visit[v])continue;
		if(v==goal)return true;
		if(dfs(v,goal))return true;
	}
	return false;
}
int main(){
	int n=read(),m=0;
	while(1){
		a[++m]=read(),b[m]=read();
		if(!a[m]&&!b[m])break;
		add(a[m],b[m]);add(b[m],a[m]);
	}
	int s=read(),t=read();
	for(int i=1;i<=n;++i)
		if(!dfn[i])root=i,tarjan(i);
	for(int i=1;i<=n;++i){
		if(!cut[i])continue;
		tot=0;memset(head,0,sizeof(head));
		for(int j=1;j<=m;++j)
			if(a[j]!=i&&b[j]!=i){
				add(a[j],b[j]);add(b[j],a[j]);
			}
		memset(visit,0,sizeof(visit));
		if(!dfs(s,t)){
			printf("%d\n",i);
			return 0;
		}
	}
	puts("No solution");
    return 0;
}

posted on 2019-08-21 17:24  PPXppx  阅读(154)  评论(0编辑  收藏  举报