hihoCoder #1185 : 连通性·三

#1185 : 连通性·三

题意:从1出发,求经过路径的最大权值和。

题目链接

对于有向图上的2个点a,b,若存在一条从a到b的路径,也存在一条从b到a的路径,那么称a,b是强连通的。
对于有向图上的一个子图,若子图内任意点对(a,b)都满足强连通,则称该子图为强连通子图。
非强连通图有向图的极大强连通子图,称为强连通分量

思路:先通过tarjan对有向图中的环进行缩点,得到的缩点的权值是原本环的权值和,我这里是通过fa[u]表示u在Ans的第fa[u]个Vector向量中,f[i]表示Ans的第i个Vector向量的所有点的缩点。得到缩点的图后,在1点进行bfs遍历一遍即可。

 
 
#include<bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 10;
const int INF = int(1e9);
struct tarjan {     //tarjan模板
	int n;
	vector<int>e[maxn];    //边集
	int dfn[maxn];    //dfn数组是个时间戳,就是访问那个节点的时间,也就是第几次调用dfs这个函数
	int low[maxn];    //Low是u的子节点能通过反向边到达的节点DFN的最小值, 初始值为dfn[u]
	int index;        //记录dfs调用的次数
	int stk[maxn];    //模拟堆栈
	int fa[maxn];     //类似染色标记,fa[u]指的是u在Ans的第几个vector中
	int top;          //模拟栈中的下标变换
	int f[maxn];      //f[i]指的是第i个vector对于的最小编号
	int ins[maxn];
	int vla[maxn];
	vector<vector<int> >Ans;    //进行环缩点后的集合
	void init(int N) {       //初始化
		n = N;
		Ans.clear();
		for (int i = 1; i <= n; i++)
			e[i].clear();
		top = 0;
		index = 0;
		memset(dfn, -1, sizeof(dfn));
		memset(fa, 0, sizeof(fa));
		fill(f, f + n, INF);
	}
	void addedge(int u, int v) {   //添加边
		e[u].push_back(v);
	}
	void dfs(int u) {       //dfs缩点
		dfn[u] = low[u] = ++index;
		stk[top++] = u;
		ins[u] = true;
		for (int i = 0; i<e[u].size(); i++) {
			int &v = e[u][i];
			if (dfn[v] == -1) {
				dfs(v);
				low[u] = min(low[u], low[v]);
			} else if (ins[v])
				low[u] = min(low[u], dfn[v]);
		}
		if (dfn[u] == low[u]) {
			vector<int>ans;
			int v = stk[top - 1];
			int k = Ans.size();
			while (u != v) {
				ins[v] = false;
				while (e[v].size()>0) {
					e[u].push_back(e[v].back());
					e[v].pop_back();
				}
				vla[u] += vla[v];
				ans.push_back(v);
				fa[v] = k;       //对于环中的每一个点,fa[v]标记到它在Ans的第i个数组中
				top--;
				v = stk[top - 1];
			}
			ans.push_back(u);
			ins[u] = false;
			fa[u] = k;
			f[k] = u;   //Ans第i个数组的缩点编号
			top--;
			Ans.push_back(ans);
		}
	}
	void solve() {   //遍历所有点
		for (int i = 1; i <= n; i++) {
			if (dfn[i] == -1)
				dfs(i);
		}
	}

} T;
int Max;
int que[maxn];
int num[maxn];
void bfs(int a) {
	int s = 0, t = 0;
	que[t++] = a;
	while (s <= t) {
		int u = que[s++];
		for (int i = 0; i<T.e[u].size(); i++) {
			int v = T.f[T.fa[T.e[u][i]]];
			if (T.f[T.fa[u]] == v)
				continue;
			num[v]= max(num[v], T.vla[v] + num[u]);
			que[t++] = v;
			Max = max(Max, num[v]);
		}
	}
	return;
}
int main() {
	int n, m;
	int u, v;
	scanf("%d %d", &n, &m);
	T.init(n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &T.vla[i]);
	}
	for (int i = 1; i <= m; i++) {
		scanf("%d %d", &u, &v);
		T.addedge(u, v);
	}
	T.dfs(1);
	memset(que, 0, sizeof(que));
	memset(num, 0, sizeof(num));
	v = T.f[T.fa[1]];
	Max = T.vla[v];
	num[v] = T.vla[v];
	bfs(v);
	printf("%d\n", Max);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40160605/article/details/80041415