题目链接:点击打开链接
思路:如果没有环, 该题就是DAG上最长路, 现在有环, 我们把强连通分量缩点, 那么缩点之后的图就是一个DAG, 可以用DP求解, 用d[i]表示以i结尾的最长路距离。
细节参见代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <string> #include <vector> #include <stack> #include <bitset> #include <cstdlib> #include <cmath> #include <set> #include <list> #include <deque> #include <map> #include <queue> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; typedef long long ll; typedef long double ld; const ld eps = 1e-9, PI = 3.1415926535897932384626433832795; const int mod = 1000000000 + 7; const int INF = 0x3f3f3f3f; // & 0x7FFFFFFF const int seed = 131; const ll INF64 = ll(1e18); const int maxn = 1e3 + 10; int T,n,m,u,v,pre[maxn],kase=0,lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt,d[maxn], vis[maxn],cnt[maxn]; vector<int> g[maxn], G[maxn ]; stack<int> S; void dfs(int u) { pre[u] = lowlink[u] = ++dfs_clock; S.push(u); int len = g[u].size(); for(int i = 0; i < len; i++) { int v = g[u][i]; if(!pre[v]) { dfs(v); lowlink[u] = min(lowlink[u], lowlink[v]); } 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; if(x == u) break; } } } void find_scc(int n) { for(int i = 1; i <= n; i++) { if(!pre[i]) dfs(i); } } void init(int n) { dfs_clock = scc_cnt = 0; for(int i = 1; i <= n; i++) { g[i].clear(); sccno[i] = pre[i] = 0; } } int dp(int i) { int& ans = d[i]; if(vis[i] == kase) return ans; vis[i] = kase; int len = G[i].size(); if(len == 0) return ans = cnt[i]; ans = 0; for(int j = 0; j < len; j++) { int v = G[i][j]; ans = max(ans, dp(v) + cnt[i]); } return ans; } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); init(n); for(int i = 1; i <= m; i++) { scanf("%d%d",&u,&v); g[u].push_back(v); } find_scc(n); for(int i = 1; i <= scc_cnt; i++) G[i].clear(), cnt[i] = 0; for(int i = 1; i <= n; i++) cnt[sccno[i]]++; for(int u = 1; u <= n; u++) { int len = g[u].size(); for(int j = 0; j < len; j++) { int v = g[u][j]; if(sccno[u] != sccno[v]) G[sccno[u]].push_back(sccno[v]); } } int ans = 0; ++kase; for(int i = 1; i <= scc_cnt; i++) { int cur = dp(i); ans = max(ans, cur); } printf("%d\n", ans); } return 0; }