1. 程式人生 > 實用技巧 >強連通分量-高速公路

強連通分量-高速公路

題目大意:

  某國有n個城市,為了使得城市間的交通更便利,該國國王打算在城市之間修一些高速公路,由於經費限制,國王打算第一階段先在部分城市之間修一些單向的高速公路。
  現在,大臣們幫國王擬了一個修高速公路的計劃。看了計劃後,國王發現,有些城市之間可以通過高速公路直接(不經過其他城市)或間接(經過一個或多個其他城市)到達,而有的卻不能。如果城市A可以通過高速公路到達城市B,而且城市B也可以通過高速公路到達城市A,則這兩個城市被稱為便利城市對。
  國王想知道,在大臣們給他的計劃中,有多少個便利城市對。

這個題的思路就是一個模板題,具體就是求強連通分量,這裡使用tarjan演算法

程式碼:

#include <iostream>
#include 
<cstring> #include <stack> using namespace std; const int N=1e4+10; const int M=1e5+10; typedef long long ll; int h[N],ne[M],to[M],idx=0; int low[N],dfn[N]; stack<int> st; int inst[N],tt=0; void add(int a,int b){ ne[idx]=h[a]; to[idx]=b; h[a]=idx++; } ll ans=0; void tarjan(int
u){ dfn[u]=low[u]=++tt; st.push(u); inst[u]=1; for(int i=h[u];~i;i=ne[i]){ int v=to[i]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else if(inst[v]){ low[u]=min(low[u],dfn[v]); } } ll cnt=0;
if(low[u]==dfn[u]){ while(1){ int t=st.top(); st.pop(); inst[t]=0; cnt++; if(t==u){ break; } } } if(cnt>1)ans+=(cnt*1ll*(cnt-1))/2; } int main(){ int n,m; cin>>n>>m; memset(h,-1,sizeof h); for(int i=0;i<m;i++){ int a,b; cin>>a>>b; add(a,b); } for(int i=1;i<=n;i++){ if(!dfn[i]){ tarjan(i); } } cout<<ans<<endl; }