CSP之高速公路(Kosaraju演算法,正反向DFS,強連通子圖分解演算法,第二次做)
阿新 • • 發佈:2018-12-10
問題描述
試題編號: | 201509-4 |
試題名稱: | 高速公路 |
時間限制: | 1.0s |
記憶體限制: | 256.0MB |
問題描述: |
問題描述 某國有n個城市,為了使得城市間的交通更便利,該國國王打算在城市之間修一些高速公路,由於經費限制,國王打算第一階段先在部分城市之間修一些單向的高速公路。 現在,大臣們幫國王擬了一個修高速公路的計劃。看了計劃後,國王發現,有些城市之間可以通過高速公路直接(不經過其他城市)或間接(經過一個或多個其他城市)到達,而有的卻不能。如果城市A可以通過高速公路到達城市B,而且城市B也可以通過高速公路到達城市A,則這兩個城市被稱為便利城市對。 國王想知道,在大臣們給他的計劃中,有多少個便利城市對。 輸入格式 輸入的第一行包含兩個整數n, m,分別表示城市和單向高速公路的數量。 接下來m行,每行兩個整數a, b,表示城市a有一條單向的高速公路連向城市b。 輸出格式 輸出一行,包含一個整數,表示便利城市對的數量。 樣例輸入 5 5 1 2 2 3 3 4 4 2 3 5 樣例輸出 3 樣例說明 城市間的連線如圖所示。有3個便利城市對,它們分別是(2, 3), (2, 4), (3, 4),請注意(2, 3)和(3, 2)看成同一個便利城市對。 評測用例規模與約定 前30%的評測用例滿足1 ≤ n ≤ 100, 1 ≤ m ≤ 1000; 前60%的評測用例滿足1 ≤ n ≤ 1000, 1 ≤ m ≤ 10000; 所有評測用例滿足1 ≤ n ≤ 10000, 1 ≤ m ≤ 100000。 |
#include<iostream> #include<cstdio> #include<stdio.h> #include<cstdlib> #include<vector> #include<stdlib.h> #include<algorithm> #include<string.h> #include<cstring> using namespace std; const int maxn=10050; int n,m,u,v; vector<int> g[maxn]; vector<int> rg[maxn]; vector<int> vs; vector<int> DAG[maxn]; bool used[maxn]; int cmp[maxn]; void addedge(int u,int v){ g[u].push_back(v); rg[v].push_back(u); } void dfs(int v){ used[v]=true; for(int i=0;i<g[v].size();i++) if (!used[g[v][i]]) dfs(g[v][i]); vs.push_back(v); } void rdfs(int v,int k){ used[v]=true; DAG[k].push_back(v); cmp[v]=k; for(int i=0;i<rg[v].size();i++) if (!used[rg[v][i]]) rdfs(rg[v][i],k); } int scc(){ memset(used,0,sizeof(used)); vs.clear(); for(int v=0;v<n;v++) if (!used[v]) dfs(v); memset(used,0,sizeof(used)); int k=0; for(int i=vs.size()-1;i>=0;i--) if (!used[vs[i]]) rdfs(vs[i],k++); return k; } int main(){ //freopen("a.txt","r",stdin); while(scanf("%d%d",&n,&m)!=EOF){ for(int i=0;i<=n;i++){ g[i].clear(); rg[i].clear(); } memset(cmp,0,sizeof(cmp)); while(m--){ scanf("%d%d",&u,&v); addedge(u-1,v-1); } int num=scc(),ans=0; u=0,v=0; for(int i=0;i<num;i++) { int cnt=DAG[i].size(); if(cnt>1) { u=i; ans+=((cnt-1)*cnt/2); } } printf("%d\n",ans); } return 0; }