[CCF CSP]201509-4 高速公路
思路:先缩点,每个强连通分量对答案的贡献为sum*(sum-1)/2 ,其中sum为强连通分量大小
用tarjan算法求强连通分量(自己写了一个前向星版本的挂了,只有10分,tarjan算法的框架还是要背熟练!!!
#include<bits/stdc++.h> using namespace std; const int N = 10005; vector<int> g[N]; stack<int> s; int cnt,vis[N], dfn[N], low[N],ans; void tarjan(int u) { dfn[u] = low[u] = ++cnt; s.push(u); vis[u]=1; for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if (!dfn[v]) { tarjan(v); low[u] = min(low[u], low[v]); } else if (vis[v]) low[u] = min(low[u], dfn[v]);//编写时易错,是dfn而不是low } if (dfn[u] == low[u]) { int sum=0; while (true) { int x = s.top(); s.pop(); sum++; vis[x]=0; if (x == u) break; } ans+=sum*(sum-1)/2; } } int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int n, m; cin >> n >> m; int u, v; for (int i = 1; i <= m; i++) { cin >> u >> v; g[u].push_back(v); } memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(vis, 0, sizeof(vis)); cnt = 0, ans = 0; for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i); cout << ans << endl; return 0; }