思路:先缩点,再构图,最后dp。dp[u] = max(dp[u],dfs(v) + val[u]);
#include <iostream> #include <stack> #include <vector> #include <cstdio> #include <cstring> using namespace std; const int maxn = 1e3 + 10; int low[maxn],pre[maxn],sccno[maxn]; int scc_cnt,dfs_colok; stack<int> s; vector<int> G[maxn],mp[maxn]; void dfs(int u){ low[u] = pre[u] = ++dfs_colok; s.push(u); for (int i = 0;i < G[u].size();++i){ int v = G[u][i]; if (!pre[v]){ dfs(v); low[u] = min(low[v],low[u]); }else if (!sccno[v]) low[u] = min(low[u],pre[v]); } if (low[u] == pre[u]){ scc_cnt++; for (;;){ int x = s.top(); s.pop(); sccno[x] = scc_cnt; if (x == u) break; } } } void find_scc(int n){ dfs_colok = scc_cnt = 0; memset(sccno, 0, sizeof sccno); memset(pre, 0,sizeof pre); for (int i = 0;i < n;i++) if (!pre[i]) dfs(i); } int val[maxn]; void build(int n){ for (int i = 1;i <= scc_cnt;i++) mp[i].clear(); memset(val, 0,sizeof val); for (int i = 0;i < n;i++){ val[sccno[i]]++; // cout << val[sccno[i]] << endl; } for (int i = 0;i < n;i++){ for (int j = 0;j < G[i].size();j++){ int v = G[i][j]; if (sccno[i] != sccno[v]){ mp[sccno[i]].push_back(sccno[v]); } } } } int dp[maxn]; int search(int u){ if (dp[u] != -1) return dp[u]; dp[u] = val[u]; for (int i = 0;i < mp[u].size();i++){ int v = mp[u][i]; dp[u] = max(dp[u],search(v) + val[u]); } // cout << dp[u] << endl; return dp[u]; } int main(){ // freopen("in.txt","r",stdin); // freopen("out","w",stdout); int n,m,t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for (int i = 0;i < n;i++) G[i].clear(); int a,b; for (int i = 1;i <= m;i++){ scanf("%d%d",&a,&b); a--; b--; G[a].push_back(b); } find_scc(n); // cout << "scc_cnt = " << scc_cnt << endl; build(n); memset(dp, -1,sizeof dp); int ans = 0; // for (int i = 1;i <= scc_cnt;i++) for (int i = 0;i < n;i++) ans = max(ans,search(sccno[i])); printf("%d\n", ans); } return 0; }