题目链接:http://poj.org/problem?id=3160
很陈旧的题目吧算是, 缩点后得到DAG, 然后就是带点权的最长路, 唯一值得注意的是一开始的图的点权可能是负的, 由于可以经过某个点但不取该点的权值, 所以可以把负的权值当做0来处理。。。
#include <cstdio>
#include <stack>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
const int N = 30005;
const int M = N * 11;
struct Main {
struct Edge {
int v;
Edge* next;
void init(int a, Edge* e) {
v = a, next = e;
}
};
Edge E[M];
Edge* head[N], * it;
int W[N];
int dp[N], n;
void init(int n) {
this->n = n;
for (int i = 0; i < n; i++) {
head[i] = 0, W[i] = 0, dp[i] = -1;
}
it = E;
}
void add(int u, int v) {
it->init(v, head[u]);
head[u] = it++;
}
int dfs(int u) {
if (dp[u] != -1) return dp[u];
int& tmp = dp[u];
tmp = 0;
for (Edge* e = head[u]; e; e = e->next) {
int v = e->v;
tmp = max(tmp, dfs(v));
}
tmp += W[u];
return tmp;
}
int gao() {
int res = -1;
for (int i = 0; i < n; i++)
if (dp[i] == -1)
dfs(i);
for (int i = 0; i < n; i++)
res = max(res, dp[i]);
return res;
}
}sol;
struct SCC {
struct Edge {
int v;
Edge* next;
void init(int a, Edge* e) {
v = a, next = e;
}
};
Edge E[M], * head[N];
int low[N], pre[N], no[N], W[N];
int n, tot, sum, tdfn;
stack<int> stk;
void init(int n) {
this->n = n;
for (int i = 0; i < n; i++) {
head[i] = 0;
no[i] = -1;
pre[i] = 0;
}
tot = 0, sum = 0, tdfn = 0;
}
void add(int u, int v) {
E[tot].init(v, head[u]);
head[u] = &E[tot++];
}
void dfs(int u) {
pre[u] = low[u] = ++tdfn;
stk.push(u);
for (Edge* e = head[u]; e; e = e->next) {
int v = e->v;
if (!pre[v]) {
dfs(v);
low[u] = min(low[u], low[v]);
}
else if (no[v] == -1)
low[u] = min(low[u], pre[v]);
}
if (low[u] == pre[u]) {
sum++;
while(1) {
int x = stk.top();
stk.pop();
no[x] = sum - 1;
if (x == u) break;
}
}
}
int run() {
for (int i = 0; i < n; i++)
if (pre[i] == 0)
dfs(i);
for (int i = 0; i < n; i++)
if (W[i] < 0) W[i] = 0;
int res = 0;
if (sum == 1) {
for (int i = 0; i < n; i++)
res += W[i];
}
else {
sol.init(n);
for (int i = 0; i < n; i++)
sol.W[no[i]] += W[i];
for (int u = 0; u < n; u++)
for (Edge* e = head[u]; e; e = e->next) {
int v = e->v;
if (no[u] != no[v])
sol.add(no[u], no[v]);
}
res = sol.gao();
}
return res;
}
}G;
int main() {
int n, m, u, v, w;
while (~scanf("%d%d", &n, &m)) {
G.init(n);
for (int i = 0; i < n; i++)
scanf("%d", &G.W[i]);
for (int i = 0; i < m; i++) {
scanf("%d%d", &u, &v);
G.add(u, v);
}
printf("%d\n", G.run());
}
return 0;
}