https://vjudge.net/problem/UVA-11324
把每个强连通分量缩成一个点,构造新图
在新图上搞个记忆化搜索
施工完毕
#include<cstdio> #include<cstring> #include<algorithm> #include<stack> #include<vector> using namespace std; const int maxn = 1007; stack<int>S; int dfn[maxn], low[maxn], sccno[maxn], val[maxn], dp[maxn], scc_cnt, dfs_cnt; vector<int>G[maxn], M[maxn]; void tarjan(int u){ dfn[u] = low[u] = ++dfs_cnt; 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(!sccno[v]){ low[u] = min(low[u], dfn[v]); } } if(low[u] == dfn[u]){ scc_cnt++; while(1){ int tmp = S.top(); S.pop(); sccno[tmp] = scc_cnt; if(tmp == u) break; } } } void findscc(int n){ memset(dfn, 0, sizeof dfn); memset(sccno, 0, sizeof sccno); scc_cnt = dfs_cnt = 0; for(int i = 1; i <= n; i++){ if(!dfn[i]) tarjan(i); } } void test(int n){ for(int i = 1; i <= n; i++){ printf("%d ", sccno[i]); } } int treedp(int u){ if(dp[u] != -1) return dp[u]; dp[u] = val[u]; int det = 0; for(int i = 0; i < M[u].size(); i++){ int v = M[u][i]; det = max(det, treedp(v)); } dp[u] += det; return dp[u]; } int solve(int n){ memset(val, 0, sizeof val); for(int i = 1; i <= n; i++){ val[sccno[i]]++; } for(int i = 1; i <= scc_cnt; i++) M[i].clear(); for(int i = 1; i <= n; i++){ for(int j = 0; j < G[i].size(); j++){ int v = G[i][j]; if(sccno[i] != sccno[v]) M[sccno[i]].push_back(sccno[v]); } } memset(dp, -1, sizeof dp); int ans = 0; for(int i = 1; i <= scc_cnt; i++){ if(dp[i] == -1){ ans = max(ans, treedp(i)); } } return ans; } int main(){ int t; scanf("%d", &t); while(t--){ int n, m; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) G[i].clear(); while(m--){ int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); } findscc(n); //test(n); printf("%d\n", solve(n)); } return 0; } /* 4 5 5 1 2 2 3 3 1 4 1 5 2 5 5 1 2 2 3 3 1 4 1 5 2 5 5 1 2 2 3 3 1 4 1 5 2 5 5 1 2 2 3 3 1 4 1 5 2 */