P3387 缩点

2021/8/10 23:38:03

本文主要是介绍P3387 缩点,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

\(Tarjan\) 模板

#include<cstdio>
#include<queue>
#include<iostream>
#define re register
using namespace std;

const int N = 1e4 + 5;
int n, m, a[N], h1[N], h2[N];
struct edge{int nxt, to;}e1[N * 10], e2[N * 10];

inline void add1(int u, int v)
{
	static int tot1 = 0;
	e1[++tot1] = edge{h1[u], v}, h1[u] = tot1;
}
inline void add2(int u, int v)
{
	static int tot2 = 0;
	e2[++tot2] = edge{h2[u], v}, h2[u] = tot2;
}

int dfn[N], low[N], col[N], vis[N], st[N], top, dfc, color;
void tarjan(int x)
{
	dfn[x] = low[x] = ++dfc, st[++top] = x, vis[x] = 1;
	for(re int i = h1[x]; i; i = e1[i].nxt)
	{
		int v = e1[i].to;
		if (!dfn[v]) tarjan(v), low[x] = min(low[x], low[v]);
		else if (vis[v]) low[x] = min(low[x], dfn[v]);
	}
	if (dfn[x] == low[x])
	{
		col[x] = ++color, vis[x] = 0;
		while (st[top] ^ x) col[st[top]] = color, vis[st[top]] = 0, --top;
		--top;
	}
}

queue<int> Q;
int f[N], val[N], in[N];
int topu()
{
	for(re int i = 1; i <= color; i++)
	if (!in[i]) Q.push(i), f[i] = val[i], vis[i] = 1;
	while (!Q.empty())
	{
		int now = Q.front(); Q.pop();
		for(re int i = h2[now]; i; i = e2[i].nxt)
		{
			--in[e2[i].to], f[e2[i].to] = max(f[e2[i].to], f[now] + val[e2[i].to]);
			if (!in[e2[i].to]) Q.push(e2[i].to);
		}
	}
	int res = 0;
	for(re int i = 1; i <= color; i++) res = max(res, f[i]);
	return res;
}

int main()
{
	scanf("%d%d", &n, &m);
	for(re int i = 1; i <= n; i++) scanf("%d", &a[i]);
	for(re int i = 1, u, v; i <= m; i++) scanf("%d%d", &u, &v), add1(u, v);
	for(re int i = 1; i <= n; i++)
	if (!dfn[i]) tarjan(i);
	for(re int i = 1; i <= n; i++)
	{
		val[col[i]] += a[i];
		for(re int j = h1[i]; j; j = e1[j].nxt)
		if (col[i] ^ col[e1[j].to]) add2(col[i], col[e1[j].to]), ++in[col[e1[j].to]];
	}
	printf("%d\n", topu());
}


这篇关于P3387 缩点的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程