洛谷-P5058 嗅探器
嗅探器
tarjan 割点
考虑以 \(a\) 作为根进行一次 \(tarjan\) 的搜索,会发现只有到 \(b\) 的路径上的割点才有可能是最终的答案
因此考虑一边标记这个路径,一边在这个路径上找割点即可
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 2e5 + 10;
vector<int>gra[maxn];
int dfn[maxn], low[maxn], tp = 0;
int vis[maxn], minn_ans = maxn;
int a, b;
void tarjan(int now)
{
low[now] = dfn[now] = ++tp;
int f = 0, v = 0;
for(int nex : gra[now])
{
if(dfn[nex] == 0)
{
tarjan(nex);
low[now] = min(low[now], low[nex]);
if(low[nex] >= dfn[now] && vis[nex])
f = 1;
if(vis[nex]) v = 1;
}
else
low[now] = min(dfn[nex], low[now]);
}
if(now == b || v) vis[now] = 1;
if(f && now != a && now != b)
minn_ans = min(minn_ans, now);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
while(cin >> a >> b && (a | b))
{
gra[a].push_back(b);
gra[b].push_back(a);
}
cin >> a >> b;
tarjan(a);
if(minn_ans != maxn) cout << minn_ans << endl;
else cout << "No solution" << endl;
return 0;
}