P3387 【模板】缩点

link

#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_set>
#include <cstring>
#include <queue>
#include <stack>
# define LL long long
using namespace std;

const int maxn = 10000 + 10;
const int maxm = 100000 + 10;
int w[maxn];
int sccw[maxn];
int ui[maxm];
int vi[maxm];

struct Edge {
	int to;
	int next;
}e1[maxm],e2[maxm];

int head1[maxn];
int head2[maxn];
int en1;
int en2;

void addEdge1(int from, int to) {
	e1[en1].next = head1[from];
	e1[en1].to = to;
	head1[from] = en1++;
}

void addEdge2(int from, int to) {
	e2[en2].next = head2[from];
	e2[en2].to = to;
	head2[from] = en2++;
}

int timer;
int scc_num;
int col[maxn];
int dict[maxn];
int low[maxn];
stack<int> stk;
int instack[maxn];

int indeg[maxn];
int dp[maxn];

void tarjan(int u) {
	stk.push(u);
	instack[u] = 1;
	++timer;
	dict[u] = timer;
	low[u] = timer;
	for (int i = head1[u]; i != -1; i = e1[i].next) {
		int v = e1[i].to;
		if (dict[v] == -1) {
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else {
			if (instack[v]) {
				low[u] = min(low[u], dict[v]);
			}
		}
	}
	if (low[u] == dict[u]) {
		++scc_num;
		while (stk.top() != u) {
			int t = stk.top();
			stk.pop();
			col[t] = scc_num;
			sccw[scc_num] += w[t];
			instack[t] = 0;

		}
		stk.pop();
		instack[u] = 0;
		col[u] = scc_num;
		sccw[scc_num] += w[u];

	}
}

int main() {
	memset(head1, -1, sizeof(head1));
	memset(head2, -1, sizeof(head2));
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) scanf("%d", &w[i]);
	for (int i = 0; i < m; i++) {
		scanf("%d%d", &ui[i], &vi[i]);
		addEdge1(ui[i], vi[i]);
	}
	memset(dict, -1, sizeof(dict));
	for (int i = 1; i <= n; i++) {
		if (dict[i] == -1) {
			tarjan(i);
		}
	}

	vector<unordered_set<int>> added(scc_num + 1);
	for (int i = 0; i < m; i++) {
		if (col[ui[i]] == col[vi[i]]) continue;
		int u = col[ui[i]];
		int v = col[vi[i]];
		if (added[u].find(v) != added[u].end()) continue;
		added[u].insert(v);
		addEdge2(u, v);
		indeg[v]++;
	}
	queue<int> q;
	int res = 0;
	for (int i = 1; i <= scc_num; i++) {
		if (indeg[i] == 0) {
			q.push(i);
			dp[i] = sccw[i];
			res = max(res, dp[i]);
		}
	}

	while (!q.empty()) {
		int cur = q.front();
		q.pop();
		for (int i = head2[cur]; i != -1; i = e2[i].next) {
			int v = e2[i].to;
			dp[v] = max(dp[v], dp[cur] + sccw[v]);
			res = max(res, dp[v]);
			indeg[v]--;
			if (indeg[v] == 0) q.push(v);
		}
	}

	printf("%d", res);
	return 0;
}
posted @ 2020-06-20 17:42  feibilun  阅读(87)  评论(0编辑  收藏  举报