Question Link
A directed graph is provided to determine whether any two points in the graph have a reachable path (one-way reachable ).
Idea: a directed graph is used to locate the strongly connected component and scale down the vertex. Because the question requires any two points to have accessible paths, the point after the contraction must form a single link to meet the reachable requirements, here, we use DP to find the longest path to determine whether a single link can be formed.
Code:
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;const int MAXN = 2010;const int MAXM = 50010;struct Edge{ int to, next;}edge[MAXM];int head[MAXN], tot;int Low[MAXN], DFN[MAXN], Stack[MAXN], Belong[MAXN];int Index, top;int scc;bool Instack[MAXN];int num[MAXN];int n, m;int d[MAXN];vector<int> g[MAXN];void init() { tot = 0; memset(head, -1, sizeof(head));}void addedge(int u, int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++;}void Tarjan(int u) { int v; Low[u] = DFN[u] = ++Index; Stack[top++] = u; Instack[u] = true; for (int i = head[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (!DFN[v]) { Tarjan(v); if (Low[u] > Low[v]) Low[u] = Low[v]; } else if (Instack[v] && Low[u] > DFN[v]) Low[u] = DFN[v]; } if (Low[u] == DFN[u]) { scc++; do { v = Stack[--top]; Instack[v] = false; Belong[v] = scc; num[scc]++; } while (v != u); }}void solve() { memset(Low, 0, sizeof(Low)); memset(DFN, 0, sizeof(DFN)); memset(num, 0, sizeof(num)); memset(Stack, 0, sizeof(Stack)); memset(Instack, false, sizeof(Instack)); Index = scc = top = 0; for (int i = 1; i <= n; i++) if (!DFN[i]) Tarjan(i);}int dp(int i) { int& ans = d[i]; if (ans > 0) return ans; ans = 1; for (int j = 0; j < g[i].size(); j++) { int v = g[i][j]; ans = max(ans, dp(v) + 1); } return ans;}int main() { int cas; scanf("%d", &cas); while (cas--) { init(); scanf("%d%d", &n, &m); int u, v; for (int i = 0; i < m; i++) { scanf("%d%d", &u, &v); addedge(u, v); } solve(); if (scc == 1) { printf("Yes\n"); continue; } else { for (int i = 0; i <= scc; i++) g[i].clear(); for (int u = 1; u <= n; u++) { for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (Belong[u] != Belong[v]) g[Belong[u]].push_back(Belong[v]); } } memset(d, -1, sizeof(d)); int ans = 0; for (int i = 1; i <= scc; i++) ans = max(ans, dp(i)); if (ans == scc) printf("Yes\n"); else printf("No\n"); } } return 0;}
POJ2762-Going from u to V or from V to u? (Strongly connected contraction point + dp)