You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
2.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
const int N = 100010, M = 2000010; // 因为要建新图,两倍的边
int n, m; // 点数、边数
int dfn[N], low[N], ts;
int stk[N], top, in_stk[N];
int id[N], scc_cnt, sz[N];
int f[N];
int h[N], hs[N], e[M], ne[M], idx; // h: 原图hs: 新图
void add(int h[], int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int p[N]; //原图的点权
int q[N]; //新图的点权
// tarjan求强连通分量
void tarjan(int u) {
dfn[u] = low[u] = ++ts;
stk[++top] = u;
in_stk[u] = true;
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (!dfn[j]) {
tarjan(j);
low[u] = min(low[u], low[j]);
} else if (in_stk[j])
low[u] = min(low[u], dfn[j]);
}
if (dfn[u] == low[u]) {
++scc_cnt;
int x;
do {
x = stk[top--];
in_stk[x] = false;
id[x] = scc_cnt;
sz[scc_cnt]++;
// scc_cnt:强连通块的编号
q[scc_cnt] += p[x]; //叠加点权,生成连通块的总点权
} while (x != u);
}
}
int main() {
memset(h, -1, sizeof h); //原图
memset(hs, -1, sizeof hs); //新图
scanf("%d %d", &n, &m);
//读入点权
for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
for (int i = 1; i <= m; i++) {
int a, b;
scanf("%d %d", &a, &b);
add(h, a, b);
}
//利用强连通分量缩点生成DAG
for (int i = 1; i <= n; i++)
if (!dfn[i]) tarjan(i);
// (2) 缩点,建图
for (int u = 1; u <= n; u++)
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
int a = id[u], b = id[j];
if (a != b) //去重边
add(hs, a, b); //加入到新图
}
// (3) 根据拓扑序遍历DAG从scc_cnt向前遍历自然满足拓扑序
for (int u = scc_cnt; u; u--) {
// base case 递推起点
if (!f[u]) f[u] = q[u];
for (int i = hs[u]; ~i; i = ne[i]) {
int j = e[i]; // 边(i, j)
if (f[j] < f[u] + q[j]) f[j] = f[u] + q[j];
}
}
// (4) 求解答案
int res = 0;
for (int i = 1; i <= scc_cnt; i++) res = max(res, f[i]);
//输出
printf("%d\n", res);
return 0;
}