社区讨论

50pts求条

P3387【模板】缩点参与者 1已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@mj18wfhn
此快照首次捕获于
2025/12/11 17:38
2 个月前
此快照最后确认于
2025/12/13 17:25
2 个月前
查看原帖
似乎 tarjan 没错(我抄的强连通分量的板子),但只有 50,可能是 dp 错了。
CPP
#include <bits/stdc++.h>

using namespace std;
#define ll long long
#define ull unsigned long long
#define db double
#define sz(x) ((int)x.size())
#define inf (1 << 30)
#define pb push_back
#define all(x) x.begin(), x.end()
typedef pair<int, int> PII;
const int N = 100000 + 7;
const int P = 998244353;
int read() {
	int x = 0, f = 1;
	char ch = getchar();
	while (!(ch >= '0' && ch <= '9')) {if (ch == '-') f = -f;ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}
	return x * f;
}
int n, m;
int dfn[N], low[N], stk[N], ins[N], top, times, c[N], dp[N]; 
int bel[N], a[N], scc, d[N], q[N], front = 1, rear = 0;
vector <int> edges[N], g[N];
void tarjan(int u) {
	dfn[u] = low[u] = ++times;
	stk[++top] = u;
	ins[u] = 1;
	for (auto v : edges[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]) {
		++scc;
		while (1) {
			int v = stk[top--];
			ins[v] = 0;
			// do sth here
			bel[v] = scc;
			a[scc] += c[v];
			if (v == u) break;
		}
	}
}
void topusort() {
	for (int i = 1; i <= scc; i++)
		if (!d[i]) q[++rear] = i;
	while (front <= rear) {
		int u = q[front++];
		for (auto v : g[u]) {
			if (--d[v] == 0) {
				q[++rear] = v;
			}
		}
	}
}
int main() {
	n = read(), m = read();
	for (int i = 1; i <= n; i++) c[i] = read();
	for (int i = 1; i <= m; i++) {
		int x = read(), y = read();
		edges[x].push_back(y);
	}
	for (int i = 1; i <= n; i++) {
		if (!dfn[i]) tarjan(i);
	}
	for (int i = 1; i <= n; i++) {
		for (auto v : edges[i]) {
			if (bel[i] != bel[v]) {
				g[bel[i]].pb(bel[v]);
				d[bel[v]]++;
			}
		}
	}
	topusort();
	for (int i = 1; i <= scc; i++) {
		for (auto v : g[i]) {
			dp[v] = max(dp[v], dp[i] + a[i]);
		}
	}
	// for (int i = 1; i <= n; i++)
	// 	printf("%d\n", a[i]);
	printf("%d\n", *max_element(dp + 1, dp + scc + 1) + *max_element(a + 1, a + scc + 1));
	return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...