我们可以发现 一个强联通分量内的点是可以任意到达的
我们不妨把它缩成一个点 这样子就成了一个
DAG
D
A
G
当然这个时候也不要忘了判断缩点后的重边
直接dp搞一下就好了
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N = 1e5 + 10;
vector<int> G1[N], G2[N], kuai[N];
int n, m, mod, be[N], color, size[N];
int de[N], f[N], cnt[N];
map<int, int> G[N];
namespace Tarjan {
int low[N], dfn[N], Sta[N], cnt, top, ins[N];
void dfs(int x) {
dfn[x] = low[x] = ++ cnt; Sta[++ top] = x; ins[x] = size[x] = 1;
for(int j = 0, sz = G1[x].size(); j < sz; ++ j) {
if(!dfn[G1[x][j]]) {
dfs(G1[x][j]);
low[x] = min(low[x], low[G1[x][j]]);
}
else if(ins[G1[x][j]])
low[x] = min(low[x], dfn[G1[x][j]]);
}
if(low[x] == dfn[x]) {
++ color;
do {
kuai[color].pb(Sta[top]);
ins[Sta[top]] = 0;
be[Sta[top]] = color;
}while(x != Sta[top --]);
}
}
void New_Graph() {
for(int i = 1; i <= color; ++ i) {
size[i] = kuai[i].size();
for(auto u : kuai[i])
for(auto v : G1[u])
if(be[u] != be[v] && !G[be[u]][be[v]])
G2[be[u]].pb(be[v]), ++ de[be[v]], G[be[u]][be[v]] = 1;
}
}
}
void Topsort() {
queue<int> q;
for(int i = 1; i <= color; ++ i)
if(!de[i]) {
q.push(i); f[i] = size[i]; cnt[i] = 1;
}
while(!q.empty()) {
int k = q.front(); q.pop();
for(auto v : G2[k]) {
if(!(-- de[v])) q.push(v);
if(f[v] < f[k] + size[v]) {
f[v] = f[k] + size[v];
cnt[v] = 0;
}
if(f[v] == f[k] + size[v])
(cnt[v] += cnt[k]) %= mod;
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("2272.in", "r", stdin);
freopen("2272.out", "w", stdout);
#endif
int x, y, ans1 = 0, ans2;
scanf("%d%d%d", &n, &m, &mod);
for(int i = 1; i <= m; ++ i) {
scanf("%d%d", &x, &y);
G1[x].pb(y);
}
for(int i = 1; i <= n; ++ i)
if(!Tarjan::dfn[i])
Tarjan::dfs(i);
Tarjan::New_Graph();
Topsort();
for(int i = 1; i <= color; ++ i) {
if(f[i] > ans1)
ans1 = f[i], ans2 = 0;
if(f[i] == ans1)
(ans2 += cnt[i]) %= mod;
}
printf("%d\n%d", ans1, ans2);
return 0;
}