题解 P5058 【[ZJOI2004]嗅探器】

题目链接

Solution [ZJOI2004]嗅探器

题目大意:给定一个无向图,求一个编号最小的点(p),使得删掉(p)(s)(t)不连通

(Tarjan)算法


分析:首先我们要明确:(p)一定是割点,因为只有你删掉一个点后图不连通才有可能使得(s)(t)不连通,然后我们可以用(tarjan)来做这个事情

常规求割点是什么,时间戳(dfn),不经过树边可以到达的最小时间戳(low)

如果存在(u)以及它的子节点(v),如果有(dfn[u] leq low[v])那么(u)就是割点,因为去掉(u)后以(v)为根的子树就和图不连通了

所以我们以(s)为根做(tarjan),只要在(u)是割点时判断一下(t)在不在以(v)为根的子树内就好了,这个显然是(dfn[v] leq dfn[t])

#include <cstdio>
#include <cctype>
#include <vector>
using namespace std;
const int maxn = 128;
inline int read(){
    int x = 0;char c = getchar();
    while(!isdigit(c))c = getchar();
    while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    return x;    
}
vector<int> G[maxn];
inline void addedge(int from,int to){G[from].push_back(to);}
int dfn[maxn],low[maxn],tot,s,t,n,ans = 0x7fffffff;
void tarjan(int u,int faz){
    dfn[u] = low[u] = ++tot;
    for(int v : G[u]){
        if(!dfn[v]){
            tarjan(v,u);
            low[u] = min(low[u],low[v]);
            if(dfn[v] <= dfn[t] && dfn[u] <= low[v] && u != s)ans = min(ans,u);   
        }else if(v != faz && dfn[v])low[u] = min(low[u],dfn[v]);
    }
}
int main(){
    n = read();
    for(int u = read(),v = read();u && v;u = read(),v = read())
        addedge(u,v),addedge(v,u);
    s = read(),t = read();
    tarjan(s,-1);
    if(ans != 0x7fffffff)printf("%d
",ans); 
    else printf("No solution
");
    return 0; 
}
原文地址:https://www.cnblogs.com/colazcy/p/11622427.html