有向图
把强联通分量缩点后得到一个DAG,然后DP。
</pre><pre name="code" class="cpp">#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 1000 + 10;
vector<int> G[maxn];
int dfn[maxn], low[maxn], sccno[maxn], dfs_clock, scc_cnt;
stack<int> S;
void dfs(int u)
{
dfn[u] = low[u] = ++dfs_clock;
S.push(u);
for(int i=0; i<G[u].size(); ++i) {
int v = G[u][i];
if(!dfn[v]) {
dfs(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++;
for(;;) {
int x = S.top();
S.pop();
sccno[x] = scc_cnt;
if(x==u) break;
}
}
}
void find_scc(int n)
{
dfs_clock = scc_cnt = 0;
memset(sccno, 0, sizeof sccno );
memset(dfn, 0, sizeof dfn );
for(int i=0; i<n; ++i) {
if(!dfn[i]) dfs(i);
}
}
int size[maxn],
TG[maxn][maxn];//缩点后的SCC图-邻接矩阵
int d[maxn];
int dp(int u)
{
int & ans = d[u];
if(ans>=0) return ans;
ans = size[u];
for(int v=1; v<=scc_cnt; ++v)
if(u != v && TG[u][v]) ans=max(ans, dp(v)+size[u]);
return ans;
}
int main()
{
int T, n, m;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
for(int i=0; i<n; ++i) G[i].clear();
for(int i=0; i<m; ++i) {
int u, v;
scanf("%d%d", &u, &v);
u--;
v--;
G[u].push_back(v);
}
find_scc(n);
memset(TG, 0, sizeof TG );
memset(size, 0, sizeof size );
for(int i=0; i<n; ++i) {
size[sccno[i]]++;
for(int j=0; j<G[i].size(); ++j)
TG[sccno[i]][sccno[G[i][j]]] = 1;// 构造SCC图
}
int ans = 0;
memset(d, -1, sizeof d );
for(int i=1; i<=scc_cnt; ++i) {
ans = max(ans, dp(i));
}
printf("%d\n", ans);
}
return 0;
}