本人已用 SPFA 通过此题,但是若将 SPFA 换成 Dijkstra 或 拓扑排序总会 WA On #3 & #11。
求问这俩没有正确性吗,还是我写错了?
缩点 + Dijkstra 代码:
#include <bits/stdc++.h>
#define mkpr make_pair
#define fir first
#define sec second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 5e5 + 7;
const int inf = 0x3f3f3f3f;
int n, m, s, p;
int money[maxn], bar[maxn];
vector<int> e[maxn], scce[maxn];
int scc[maxn], siz[maxn], scc_cnt;
int dfn[maxn], low[maxn], dfn_cnt;
int sta[maxn], top;
bool ins[maxn];
void tarjan(int u) {
low[u] = dfn[u] = ++dfn_cnt;
sta[++top] = u, ins[u] = 1;
for (int v : e[u]) {
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if (ins[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if (low[u] == dfn[u]) {
int v; ++scc_cnt;
do {
v = sta[top--], ins[v] = 0;
siz[scc_cnt] += money[v];
scc[v] = scc_cnt;
} while (v != u);
}
}
int dis[maxn];
bool vis[maxn];
priority_queue<pii> pq;
void dij() {
memset(dis, -inf, sizeof(dis));
dis[scc[s]] = siz[scc[s]];
pq.push(mkpr(dis[scc[s]], scc[s]));
while (pq.size()) {
int u = pq.top().sec; pq.pop();
if (vis[u]) continue;
vis[u] = 1;
for (int v : scce[u]) {
if (dis[v] < dis[u] + siz[v]) {
dis[v] = dis[u] + siz[v];
pq.push(mkpr(dis[v], v));
}
}
}
}
unordered_set<int> uni[maxn];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++i) {
int u, v;
scanf("%d%d", &u, &v);
e[u].push_back(v);
}
for (int i = 1; i <= n; ++i)
scanf("%d", money + i);
scanf("%d%d", &s, &p);
for (int i = 1; i <= p; ++i)
scanf("%d", bar + i);
tarjan(s);
for (int u = 1; u <= n; ++u) {
for (int v : e[u]) {
if (scc[u] == scc[v]) continue;
if (uni[scc[u]].count(scc[v])) continue;
uni[scc[u]].insert(scc[v]);
scce[scc[u]].push_back(scc[v]);
}
}
dij();
int ans = 0;
for (int i = 1; i <= p; ++i)
ans = max(ans, dis[scc[bar[i]]]);
printf("%d\n", ans);
return 0;
}
缩点 + 拓扑排序代码:
#include <bits/stdc++.h>
#define mkpr make_pair
#define fir first
#define sec second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 5e5 + 7;
const int inf = 0x3f3f3f3f;
int n, m, s, p;
int money[maxn], bar[maxn];
vector<int> e[maxn], scce[maxn];
int scc[maxn], siz[maxn], scc_cnt;
int dfn[maxn], low[maxn], dfn_cnt;
int sta[maxn], top;
bool ins[maxn];
void tarjan(int u) {
low[u] = dfn[u] = ++dfn_cnt;
sta[++top] = u, ins[u] = 1;
for (int v : e[u]) {
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if (ins[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if (low[u] == dfn[u]) {
int v; ++scc_cnt;
do {
v = sta[top--], ins[v] = 0;
siz[scc_cnt] += money[v];
scc[v] = scc_cnt;
} while (v != u);
}
}
int dp[maxn];
queue<int> q;
int ind[maxn];
void tps() {
q.push(scc[s]);
dp[scc[s]] = siz[scc[s]];
while (q.size()) {
int u = q.front(); q.pop();
for (int v : scce[u]) {
dp[v] = max(dp[v], dp[u] + siz[v]);
if(--ind[v] == 0) q.push(v);
}
}
}
unordered_set<int> uni[maxn];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++i) {
int u, v;
scanf("%d%d", &u, &v);
e[u].push_back(v);
}
for (int i = 1; i <= n; ++i)
scanf("%d", money + i);
scanf("%d%d", &s, &p);
for (int i = 1; i <= p; ++i)
scanf("%d", bar + i);
tarjan(s);
for (int u = 1; u <= n; ++u) {
for (int v : e[u]) {
if (scc[u] == scc[v]) continue;
if (uni[scc[u]].count(scc[v])) continue;
uni[scc[u]].insert(scc[v]);
scce[scc[u]].push_back(scc[v]);
}
}
tps();
int ans = 0;
for (int i = 1; i <= p; ++i)
ans = max(ans, dp[scc[bar[i]]]);
printf("%d\n", ans);
return 0;
}