[APIO 2009] Atm
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=1179
[算法]
首先 , 将这张图缩点 , 然后 , SPFA最长路即可
时间复杂度 : O(KN)
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 500010 const int INF = 1e9; struct edge { int to , nxt; } e[MAXN << 1] , ec[MAXN << 1]; int tot , n , m , timer , cnt , S , P; int low[MAXN] , value[MAXN] , dfn[MAXN] , dist[MAXN] , heada[MAXN] , headb[MAXN] , belong[MAXN] , c[MAXN] , id[MAXN]; bool instack[MAXN] , inq[MAXN]; stack< int > s; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void addedgea(int u , int v) { ++tot; e[tot] = (edge){v , heada[u]}; heada[u] = tot; } inline void addedgeb(int u , int v) { ++tot; ec[tot] = (edge){v , headb[u]}; headb[u] = tot; } inline void tarjan(int u) { low[u] = dfn[u] = ++timer; s.push(u); instack[u] = true; for (int i = heada[u]; i; i = e[i].nxt) { int v = e[i].to; if (!dfn[v]) { tarjan(v); low[u] = min(low[u] , low[v]); } else if (instack[v]) low[u] = min(low[u] , dfn[v]); } if (dfn[u] == low[u]) { ++cnt; int v; do { v = s.top(); s.pop(); instack[v] = false; belong[v] = cnt; value[cnt] += c[v]; } while (v != u); } } inline void spfa(int s) { queue< int > q; for (int i = 1; i <= cnt; i++) { dist[i] = 0; inq[i] = false; } dist[s] = value[s]; q.push(s); inq[s] = true; while (!q.empty()) { int cur = q.front(); q.pop(); inq[cur] = false; for (int i = headb[cur]; i; i = ec[i].nxt) { int v = ec[i].to , w = value[v]; if (dist[cur] + w > dist[v]) { dist[v] = dist[cur] + w; if (!inq[v]) { inq[v] = true; q.push(v); } } } } } int main() { read(n); read(m); for (int i = 1; i <= m; i++) { int x , y; read(x); read(y); addedgea(x , y); } for (int i = 1; i <= n; i++) read(c[i]); read(S); read(P); for (int i = 1; i <= P; i++) read(id[i]); for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i); tot = 0; for (int u = 1; u <= n; u++) { for (int i = heada[u]; i; i = e[i].nxt) { int v = e[i].to; if (belong[u] != belong[v]) addedgeb(belong[u] , belong[v]); } } spfa(belong[S]); int ans = 0; for (int i = 1; i <= P; i++) chkmax(ans , dist[belong[id[i]]]); printf("%d\n" , ans); return 0; }