【题意】
某国有n个城市,为了使得城市间的交通更便利,该国国王打算在城市之间修一些高速公路,由于经费限制,国王打算第一阶段先在部分城市之间修一些单向的高速公路。
现在,大臣们帮国王拟了一个修高速公路的计划。看了计划后,国王发现,有些城市之间可以通过高速公路直接(不经过其他城市)或间接(经过一个或多个其他城市)到达,而有的却不能。如果城市A可以通过高速公路到达城市B,而且城市B也可以通过高速公路到达城市A,则这两个城市被称为便利城市对。
国王想知道,在大臣们给他的计划中,有多少个便利城市对。
【分析】对于一个有N个点的强连通分量会产生N*(N-1)/2对便利城市对,所有强连通分量累加即可。
【AC CODE】125ms
#include <bits/stdc++.h> using namespace std; typedef long long LL; #define rep(i,a,n) for(int i = a; i < n; i++) #define repe(i,a,n) for(int i = a; i <= n; i++) #define per(i,n,a) for(int i = n; i >= a; i--) #define clc(a,b) memset(a,b,sizeof(a)) const int INF = 0x3f3f3f3f, MAXN = 10000+10, MAXM = 100000+10; int head[MAXN],tol,nxt[MAXM],to[MAXM]; int n,pre[MAXN],sccno[MAXN],dfs_clock,scc_cnt; void add_edge(int u, int v) { nxt[tol] = head[u], to[tol] = v; head[u] = tol++; } stack<int> s; int ans; int dfs(int u) { int lowu = pre[u] = ++dfs_clock; s.push(u); for(int i = head[u]; ~i; i = nxt[i]) { int v = to[i]; if(!pre[v]) { int lowv = dfs(v); lowu = min(lowu,lowv); } else if(!sccno[v]) lowu = min(lowu,pre[v]); } if(lowu == pre[u]) { int x,cnt = 0; scc_cnt++; do{ x = s.top();s.pop(); sccno[x] = scc_cnt; cnt++; }while(x != u); ans += cnt*(cnt-1)>>1; } return lowu; } int main() { #ifdef SHY freopen("d:\\1.txt", "r", stdin); #endif int n,m; scanf("%d %d", &n,&m); clc(head,-1); tol = 0; rep(i,0,m) { int u,v; scanf("%d%d", &u,&v); add_edge(u,v); } ans = 0; repe(i,1,n) { if(!pre[i]) dfs(i); } printf("%d\n", ans); return 0; }