这份代码 GFOJ 上 50 分,求调
圣诞老人准备在圣诞节给 ACMer 送礼物,每个 ACMer 都有一个寝室,寝室之间有单向道路。每个人对于圣诞老人发的礼物都有一个心情值的影响。圣诞老人每到达一个寝室可以进去发礼物也可以不发,可以到达一个寝室多次,不能给一个寝室发多个礼物,求心情影响值之和最大值。
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 3e4 + 5, M = 1.5e5 + 5;
int n, m, tot1, tot2, head1[N], head2[N];
int cnt, top, scnt, dfn[N], low[N], stk[N], p[N];
bool instk[N], vis[N];
ll ans, a[N], w[N], dp[N];
struct edge {
int to, nxt;
} e1[M], e2[M];
void add1 (int u, int v) {
++tot1;
e1[tot1].nxt = head1[u];
e1[tot1].to = v;
head1[u] = tot1;
}
void add2 (int u, int v) {
++tot2;
e2[tot2].nxt = head2[u];
e2[tot2].to = v;
head2[u] = tot2;
}
void tarjan (int u) {
++cnt;
++top;
dfn[u] = cnt;
low[u] = cnt;
stk[top] = u;
instk[u] = true;
vis[u] = true;
for (int i = head1[u]; i; i = e1[i].nxt) {
int v = e1[i].to;
if (vis[v] == false) {
tarjan (v);
low[u] = min (low[u], low[v]);
}
if (vis[v] == true && instk[i] == true) {
low[u] = min (low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
++scnt;
int tmp = 0;
do {
tmp = stk[top];
instk[tmp] = false;
p[tmp] = scnt;
w[scnt] += a[tmp];
--top;
} while (tmp != u);
}
}
ll dfs (int u) {
if (dp[u] != 0) {
return dp[u];
}
for (int i = head2[u]; i; i = e2[i].nxt) {
int v = e2[i].to;
ll qwq = dfs (v);
if (dp[u] < qwq) {
dp[u] = qwq;
}
}
dp[u] += w[u];
return dp[u];
}
int main () {
scanf ("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf ("%lld", &a[i]);
}
for (int i = 1; i <= n; ++i) {
if (a[i] < 0) {
a[i] = 0;
}
}
for (int i = 1; i <= m; ++i) {
int u, v;
cin >> u >> v;
add1 (u + 1, v + 1);//题目的输入从 0 编号,不用管
}
for (int i = 1; i <= n; ++i) {
if (vis[i] == false) {
tarjan (i);
}
}
for (int u = 1; u <= n; ++u) {
for (int i = head1[u]; i; i = e1[i].nxt) {
int v = e1[i].to;
if (p[u] != p[v]) {
add2 (p[v], p[u]);
}
}
}
for (int i = 1; i <= scnt; ++i)
{
if (dp[i] == 0) {
dfs (i);
}
if (ans < dp[i]) {
ans = dp[i];
}
}
printf ("%lld", ans);
return 0;
}