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;
}