Question Link
Question: A directed graph is given to find the largest node set of the number of knots, so that any two knots U and V in the node set can meet the following requirements: either u can go to V, either V can reach U (U and V can reach each other)
Idea: we can reduce the point and use Tarjan to find all strongly connected components so that the weight of each SCC is equal to the number of its nodes. Because the SCC graph has a dag, use DP to solve the problem.
Code:
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <stack>#include <algorithm>using namespace std;const int MAXN = 1005;vector<int> g[MAXN], scc[MAXN], G[MAXN];stack<int> s;int pre[MAXN], lowlink[MAXN], sccno[MAXN], sccnum[MAXN], dfs_clock, scc_cnt; int d[MAXN];int n, m;int Tarjan(int u) { lowlink[u] = pre[u] = ++dfs_clock; s.push(u); for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if (!pre[v]) { Tarjan(v); lowlink[u] = min(lowlink[v], lowlink[u]); } else if (!sccno[v]) { lowlink[u] = min(lowlink[u], pre[v]); } } if (lowlink[u] == pre[u]) { scc_cnt++; for (;;) { int x = s.top(); s.pop(); sccno[x] = scc_cnt; sccnum[sccno[x]]++; if (x == u) break; } }}void find_scc() { memset(pre, 0, sizeof(pre)); memset(lowlink, 0, sizeof(lowlink)); memset(sccno, 0, sizeof(sccno)); memset(sccnum, 0, sizeof(sccnum)); dfs_clock = scc_cnt = 0; for (int i = 0; i < n; i++) if (!pre[i]) Tarjan(i);}int dp(int i) { int& ans = d[i]; if (ans > 0) return ans; ans = sccnum[i]; for (int j = 0; j < G[i].size(); j++) { int v = G[i][j]; ans = max(ans, dp(v) + sccnum[i]); } return ans;}int main() { int cas; scanf("%d", &cas); while (cas--) { scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) g[i].clear(); int u, v; for (int i = 0; i < m; i++) { scanf("%d%d", &u, &v); u--; v--; g[u].push_back(v); } find_scc(); memset(d, -1, sizeof(d)); memset(G, 0, sizeof(G)); for (int u = 0; u < n; u++) { for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if (sccno[u] != sccno[v]) G[sccno[u]].push_back(sccno[v]); } } int ans = 0; for (int i = 1; i <= scc_cnt; i++) ans = max(ans, dp(i)); printf("%d\n", ans); } return 0;}
Uva11324 -- the largest clique (SCC + dp)