Solution [ZJOI2004]嗅探器
题目大意:给定一个无向图,求一个编号最小的点\(p\),使得删掉\(p\)后\(s\)和\(t\)不连通
分析:首先我们要明确:点\(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\n",ans);
else printf("No solution\n");
return 0;
}
原文地址:https://www.cnblogs.com/colazcy/p/11622427.html
时间: 2024-10-18 07:34:46