强连通分量-高速公路
题目大意:
某国有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; }

浙公网安备 33010602011771号