#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; }