Codeforces Round #606 (Div. 2) - E. Two Fairs(割点+dfs)
#include <iostream> #include <algorithm> #include <cstdio> using namespace std; const int N = 500010; typedef long long ll; struct node { int to, nex; }; node edge[2 * N]; int t, n, m, a, b, cnt, head[N]; int dfn[N], timing, pcut[N]; int cnta, cntb, vis[N]; void dfs(int u, int mk, int a, int b) { vis[u] = 1; if (0 == mk) cnta++; if (1 == mk) cntb++; if (0 == mk && u == b) return; if (1 == mk && u == a) return; for (int i = head[u]; 0 != i; i = edge[i].nex) { int v = edge[i].to; if (!vis[v]) dfs(v, mk, a, b); } return; } void add_edge(int u, int v) { edge[++cnt].to = v; edge[cnt].nex = head[u]; head[u] = cnt; } int tarjan(int u, int fa) { int child = 0, lowu; lowu = dfn[u] = ++timing; for (int i = head[u]; 0 != i; i = edge[i].nex) { int v = edge[i].to; if (!dfn[v]) { child++; int lowv = tarjan(v, u); if (lowv >= dfn[u] && u != fa) pcut[u] = 1; lowu = min(lowu, lowv); } else if (v != fa) { lowu = min(lowu, dfn[v]); } } if (u == fa && child > 1) pcut[u] = 1; return lowu; } void init() { cnt = timing = cnta = cntb = 0; for (int i = 1; i <= n; i++) pcut[i] = dfn[i] = head[i] = 0; } int main() { scanf("%d", &t); while (t--) { scanf("%d%d%d%d", &n, &m, &a, &b); init(); for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); add_edge(u, v), add_edge(v, u); } for (int i = 1; i <= n; i++) { if (0 == dfn[i]) tarjan(i, i); } if (0 == pcut[a] || 0 == pcut[b]) { printf("0\n"); continue; } for (int i = 1; i <= n; i++) vis[i] = 0; dfs(a, 0, a, b); for (int i = 1; i <= n; i++) vis[i] = 0; dfs(b, 1, a, b); ll x = ll(n - cnta), y = ll(n - cntb); printf("%lld\n", x * y); } return 0; }