传送门:CCF201509-4 高速公路
Tarjan强连通分量算法的模板题。
求得强连通分量后,包含的点为cnt个,其中的任意两个城市都是便利城市对,数量为,亦即,将每个强连通分量的便利城市对个数累加,即是答案。
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e4+10;
int n, m, ans;
int dfn[maxn], low[maxn], vis[maxn], index;
vector <int> G[maxn];
stack <int> S;
void read()
{
cin >> n >> m;
for(int i = 0; i < m; ++i)
{
int u, v;
cin >> u >> v;
G[u].push_back(v);
}
}
void tarjan(int u)
{
dfn[u] = low[u] = ++index;
S.push(u);
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]);
}
if(low[u] == dfn[u])
{
int cnt = 0;
while(1)
{
int x = S.top();
++cnt;
S.pop();
vis[x] = 1;
if(x == u)
{
ans += (cnt-1)*cnt/2;
break;
}
}
}
}
void find_scc()
{
index = 0;
memset(vis, 0, sizeof(vis));
memset(dfn, 0, sizeof(dfn));
for(int i = 1; i <= n; ++i)
if(!dfn[i])
tarjan(i);
}
void solve()
{
find_scc();
cout << ans;
}
int main()
{
read();
solve();
return 0;
}