[ZJOI2004]嗅探器

[Time Gate]

https://www.luogu.org/problemnew/show/P5058

【解题思路】

首先非常明显的是,只能把服务器建在割点上,因为只有这样,才能捕获到全部的数据。

考虑如何求x,y两点之间的必经的割点。

很明显需要满足4个条件

考虑我们有一个u点,它连了一个v点,那么u点需要满足4个条件。

  1. u不是起点终点。因为题目要求在中间服务器上建嗅探器。
  2. u是割点。废话
  3. 终点(y)的dfn应该大于等于v点的dfn,因为要确保终点在v点或之后被访问到,即u点为必经的点。
  4. 终点(y)的low应该大于等于u点的dfn,因为要确保终点必须要经过u点。
【code】
 1 #include<cstdio>
 2 const int N=1e5+50;
 3 const int M=5e5+50;
 4 int to[M<<1],las[M<<1],fir[M<<1],cnt;
 5 inline void add_edge(int u,int v){
 6     to[++cnt]=v;las[cnt]=fir[u];fir[u]=cnt;
 7     to[++cnt]=u;las[cnt]=fir[v];fir[v]=cnt;
 8 }
 9 int dfn[N],low[N],tot;
10 int gd[N];
11 int n,m,x,y;
12 int opt,ans=N;
13 inline int max(int u,int v){return u>v?u:v;}
14 inline int min(int u,int v){return u<v?u:v;}
15 void tj(int u){
16     dfn[u]=low[u]=++tot;
17     for(int i=fir[u];i;i=las[i]){
18         if(!dfn[to[i]]){
19             tj(to[i]);
20             low[u]=min(low[u],low[to[i]]);
21             if(u!=x&&u!=y)//不是起点终点
22             if(dfn[u]<=low[to[i]]&&dfn[to[i]]<=dfn[y]&&low[y]>=dfn[x])//满足条件
23             ans=min(ans,u);//更新答案
24         }
25         low[u]=min(low[u],dfn[to[i]]);
26     }
27 }
28 int main(){
29     scanf("%d",&n);
30     while(scanf("%d%d",&x,&y),x)add_edge(x,y);
31     //建边
32     scanf("%d%d",&x,&y);//读入起点和终点
33     tj(x);//从x点tarjan
34     if(ans!=N)printf("%d\n",ans);
35     else puts("No solution");
36 }

 

posted @ 2019-07-08 20:42  GTR_PaulFrank  阅读(191)  评论(0编辑  收藏  举报