ybtoj强连通分块TarjanDP例题1有向图缩点

Posted SSL_ZZL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ybtoj强连通分块TarjanDP例题1有向图缩点相关的知识,希望对你有一定的参考价值。

【例题1】有向图缩点


Link

传送门
题目


解题思路

关于解释Tarjan这件事,这篇博客就是yyds

d i s i dis_i disi为以i为终点的最大值, s i s_i si为i点的点权值
设有一条边是 i − > j i->j i>j
d i s j = m a x ( d i s j , d i s i + s j ) dis_j = max(dis_j, dis_i+s_j) disj=max(disj,disi+sj)

优化:Tarjan -》取消了环的无用性
一个强连通分块的值是固定的,先用Tarjan求出来
再用缩出来点进行DP


Code

#include <iostream>
#include <cstdio>
#include <queue>

using namespace std;

struct DT{
	int to, next;
}Ta[500000], a[500000];
int n, m, dye, ans, num, Tnum, now, top, x[10100], y[10100];
int Ts[10100], Thead[10100], low[10100], dfn[10100], hep[10100], co[10100];
int s[10100], head[10100], dis[10100], times[10100];
queue<int>q;

void Tarjan(int x) {
	low[x] = dfn[x] = ++now;
	hep[++top] = x;
	for (int i = Thead[x]; i; i = Ta[i].next) {
		if (!dfn[Ta[i].to]) {
			Tarjan(Ta[i].to);
			low[x] = min(low[x], low[Ta[i].to]);
		}
		else if (!co[Ta[i].to])
			low[x] = min(low[x], dfn[Ta[i].to]);
	}
	if (low[x] == dfn[x]) {
		++dye;
		while(hep[top + 1] != x)
			co[hep[top--]] = dye;
	}
}

void answer() {
	for (int i = 1; i <= dye; i++) {
		dis[i] = s[i];
		if (!times[i])  //用拓扑顺序DP
			q.push(i);
	}
	while(!q.empty()) {
		int x = q.front();
		q.pop();
		for (int i = head[x]; i; i = a[i].next) {
			dis[a[i].to] = max(dis[a[i].to], dis[x] + s[a[i].to]);  //DP
			times[a[i].to]--;  //拓扑
			if (!times[a[i].to])
				q.push(a[i].to);
		}
	} 
}

int main() {
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf("%d", &Ts[i]);
	for (int i = 1; i <= m; i++) {
		scanf("%d %d", &x[i], &y[i]);
		Ta[++Tnum] = (DT){y[i], Thead[x[i]]};
		Thead[x[i]] = Tnum;
	}
	for (int i = 1; i <= n; i++)
		if (!dfn[i])
			Tarjan(i);
	for (int i = 1; i <= n; i++)
		s[co[i]] += Ts[i];  //将缩出的点的值更新
	for (int i = 1; i <= m; i++)
		if (co[x[i]] != co[y[i]]) {  //重新对点进行建图
			times[co[y[i]]]++;
			a[++num] = (DT){co[y[i]], head[co[x[i]]]};
			head[co[x[i]]] = num;
		}
	answer();
	for (int i = 1; i <= dye; i++)
		ans = max(ans, dis[i]);
	printf("%d", ans);
}

以上是关于ybtoj强连通分块TarjanDP例题1有向图缩点的主要内容,如果未能解决你的问题,请参考以下文章

算法:强连通分量缩点

有向图缩点(强连通分量)

浅谈缩点

tarjan强连通分量缩点模板

LA 4287 等价性证明(强连通分量缩点)

有向图强连通分量