NC50403 嗅探器
题目:
• 某军搞信息对抗实战演习,红军成功地侵入了蓝军的内部网络,蓝军共有两个信息中心,红军计划在某台中间服务器上安装一个嗅探器,从而能够侦听到两个信息中心互相交换的所有信息,但是蓝军的网络相当的庞大,数据包从一个信息中心传到另一个信息中心可以不止有一条通路。现在需要你尽快地解决这个问题,应该把嗅探器安装在哪个中间服务器上才能保
证所有的数据包都能被捕获?
输出编号。如果有多个解输出编号最小的一个,如果找不到任何解,输出No solution。
题解:
• 肯定是个割点,但是割点还不够
• 起点到终点不在同一个点双连通分量里
• 起点到终点的路径要经过它,且他是必经之路的第一个点——搜索
详细讲讲为什么只求割点不行?如果题目给的a,b在一个连通块里,比如图中的2和5,我们求得1为割点,即便将1去掉,2和5依旧相连,所以我们不仅要求出割点,还要验证这个割点能否将a和b隔开
现在我们从a开始tarjan
如果v是u的儿子,当dfn[u]<=low[v]时说明u是割点
删掉u后,u和v必将隔开,如果b在v的一侧,而a不再v的一侧,这样u不就将a和b隔开了吗?
b在v的一侧说明:dfn[b]>=dfn[v]
a在v的另一侧说明:dfn[a]<dfn[v]
如果a在v的一侧,b不在也是同理
代码:
#include<bits/stdc++.h> #include<vector> typedef long long ll; using namespace std; inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48); return s*w; } const int maxn=5e5+9; vector<int>edge[maxn]; int a,b; int low[maxn],dfn[maxn]; int cnt=0; int ans=1e9; bool check(int x) { if(dfn[x]<=dfn[a]&&dfn[x]>dfn[b])return 1; if(dfn[x]<=dfn[b]&&dfn[x]>dfn[a])return 1; return 0; } void tarjan(int x,int fa) { low[x]=dfn[x]=++cnt; for(int i=0;i<edge[x].size();i++) { int v=edge[x][i]; if(!dfn[v]) { tarjan(v,x); low[x]=min(low[v],low[x]); if(low[v]>=dfn[x]&&x!=a&&x!=b&&check(v)) { ans=min(ans,x); } } else if(v!=fa)low[x]=min(low[x],dfn[v]); } } int main() { int n; cin>>n; int x,y; while(cin>>x>>y) { if(x==0&&y==0)break; edge[x].push_back(y); edge[y].push_back(x); } cin>>a>>b; tarjan(a,a); if(ans==1e9)cout<<"No solution"; else cout<<ans; }