【题目链接】
先SCC缩点,在DAG上跑最长路,顺便统计出到达每个点的最长路的路径个数。
/* Pigonometry */ #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <map> using namespace std; typedef pair<int, int> pii; const int maxn = 100005, maxm = 1000005, maxs = 100005, maxq = maxs; int n, m, p, head[maxn], cnt, dfn[maxn], low[maxn], clo, belong[maxn], tot, size[maxn], du[maxn], dp[maxn], num[maxn]; int sta[maxs], top, q[maxq]; int ans1, ans2; bool ins[maxn]; struct _edge { int v, next; } g[maxm << 1]; vector<int> e[maxn]; map<pii, bool> vis; inline int iread() { int f = 1, x = 0; char ch = getchar(); for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1; for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0'; return f * x; } inline void add(int u, int v) { g[cnt] = (_edge){v, head[u]}; head[u] = cnt++; } inline void tarjan(int x) { dfn[x] = low[x] = ++clo; ins[sta[++top] = x] = 1; for(int i = head[x]; ~i; i = g[i].next) if(!dfn[g[i].v]) tarjan(g[i].v), low[x] = min(low[x], low[g[i].v]); else if(ins[g[i].v]) low[x] = min(low[x], dfn[g[i].v]); if(dfn[x] == low[x]) { tot++; while(1) { int u = sta[top--]; ins[u] = 0; belong[u] = tot; size[tot]++; if(u == x) break; } } } inline void topo() { int h = 0, t = 0; for(int i = 1; i <= tot; i++) if(!du[i]) dp[q[t++] = i] = size[i], num[i] = 1; while(h != t) { int u = q[h++]; for(int i = 0; i < e[u].size(); i++) { int v = e[u][i]; if(dp[v] < dp[u] + size[v]) { dp[v] = dp[u] + size[v]; num[v] = num[u]; } else if(dp[v] == dp[u] + size[v]) (num[v] += num[u]) %= p; du[v]--; if(!du[v]) q[t++] = v; } } } int main() { n = iread(); m = iread(); p = iread(); for(int i = 1; i <= n; i++) head[i] = -1; cnt = 0; for(int i = 1; i <= m; i++) { int u = iread(), v = iread(); add(u, v); } for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i); for(int u = 1; u <= n; u++) for(int i = head[u]; ~i; i = g[i].next) if(belong[u] != belong[g[i].v] && !vis[pii(belong[u], belong[g[i].v])]) e[belong[u]].push_back(belong[g[i].v]), du[belong[g[i].v]]++, vis[pii(belong[u], belong[g[i].v])] = 1; topo(); for(int i = 1; i <= tot; i++) if(dp[i] > ans1) ans1 = dp[i], ans2 = num[i]; else if(dp[i] == ans1) (ans2 += num[i]) %= p; printf("%d\n%d\n", ans1, ans2); return 0; }