1. 程式人生 > 實用技巧 >洛谷P5058 [ZJOI2004]嗅探器(Tarjan找割點+思維處理dfn)

洛谷P5058 [ZJOI2004]嗅探器(Tarjan找割點+思維處理dfn)

題目連結:https://www.luogu.com.cn/problem/P5058

思路:這個題其實想明白了就是一個很裸的找tarjan割點,但是這個割點的範圍在(a,b)之間,即不包括a和b,所以我們可以考慮dfn,以a作為root點跑tarjan,然後判斷是不是割點,再在割點的基礎上判(dfn[i]是否小於等於dfn[b],因為是個回溯的過程嘛,如果b賦上了dfn的值,那麼i肯定也有,如果b沒附上,那i即使大於b且i是割點,那我們也不把他當成真割點)。最後rep(i,1,n)看一下最小的真割點是誰

#include<bits/stdc++.h>
#define ll long long
#define
rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f
; const int mod=1e9+7; const int maxn=5e5+5; int tot,head[maxn]; struct E{ int to,next; }edge[maxn<<1]; void add(int u,int v){ edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } int a,b; int id[maxn],dfn[maxn],low[maxn],tott,cnt; stack<int> s;int fa[maxn],cut[maxn]; vector
<int> bccs[maxn]; void tarjan(int x){ low[x]=dfn[x]=++tott; s.push(x);int son=0; for(int i=head[x];i!=-1;i=edge[i].next){ int v=edge[i].to; if(!dfn[v]){ ++son;fa[v]=x; tarjan(v); low[x]=min(low[x],low[v]); if(low[v]>=dfn[x]){ if(dfn[v]<=dfn[b])cut[x]=true; ++cnt; bccs[cnt].clear(); while(1){ int now=s.top();s.pop(); id[now]=cnt; bccs[cnt].push_back(now); if(now==v) break; } id[x]=cnt; bccs[cnt].push_back(x); } } else if(v!=fa[x]) low[x]=min(low[x],dfn[v]); } if(fa[x]==-1&&son==1) cut[x]=false; } int m,n; int main(){ cin>>n; int u,v;mem(head,-1); while(cin>>u>>v&&u){ add(u,v);add(v,u); } cin>>a>>b; tarjan(a); rep(i,1,n){ if(i!=a&&cut[i]){ cout<<i<<endl;return 0; } } puts("No solution"); }
View Code