题目:P4017 最大食物链计数
知识点:链式前向星建图、同余原理、拓扑排序、动态规划
CODE:
cpp
#include <bits/stdc++.h>
#define MOD 80112002
using namespace std;
static const int N = 5005;
static const int M = 500005;
vector<int> head(N, 0);
vector<int> nxt(M, 0);
vector<int> to(M, 0);
vector<int> idgr(N, 0);
vector<int> odgr(N, 0);
vector<int> dp(N, 0);
int main() {
int n, m;
cin >> n >> m;
int cnt = 1;
while (m--) {
int f, t;
cin >> f >> t;
// idgr & odgr
odgr[f]++;
idgr[t]++;
// f -> t
to[cnt] = t;
nxt[cnt] = head[f];
head[f] = cnt++;
}
// ...
queue<int> q;
int ans = 0;
for (int i = 1; i <= n; i++) {
if (idgr[i] == 0) {
q.emplace(i);
dp[i] = 1;
if (odgr[i] == 0) {
ans++;
}
}
}
while (!q.empty()) {
int f = q.front();
q.pop();
int e = head[f];
while (e != 0) {
// 边 e
int v = to[e];
idgr[v]--;
// dp[v] += dp[f];
dp[v] = ((dp[v] % MOD) + dp[f]) % MOD;
if (idgr[v] == 0) {
q.emplace(v);
if (odgr[v] == 0) {
ans = ((ans % MOD) + dp[v]) % MOD;
}
}
e = nxt[e];
}
}
cout << ans << endl;
}
易错点:
①对于孤立点,要计算一次,42line
②对于拓扑排序的终点,是当入度变为 0 时才去判断是否为终点,而不是只要出度为 0 就记录,如下为错误示例,这会导致入度为复数的终点重复计算
cpp
// ...
if (idgr[v] == 0) {
q.emplace(v);
}
if (odgr[v] == 0 {
ans = ((ans % MOD) + dp[v]) % MOD;
}