# 算法：强连通分量缩点

## 例题

2 2
1 1
1 2
2 1


2


## 强连通分量缩点

1. 拓扑排序：按照拓扑序进行dp。

2. 记忆化搜索：直接暴力深搜，再加个记忆化。

3. 最长路：spfa跑一个最长路。

## 代码

# include <cstdio>
# include <algorithm>
# include <cmath>
# include <cstring>
# include <vector>
# include <queue>
# include <stack>

using namespace std;

const int N_MAX = 10000, M_MAX = 100000;

int n, m;
int u[M_MAX + 10], v[M_MAX + 10];
int a[N_MAX + 10]; // a[i]表示小点i的权值
vector <int> g[N_MAX + 10];

// 一大堆tarjan算法所用到的变量
int now, dfn[N_MAX + 10], low[N_MAX + 10];
bool ins[N_MAX + 10];
stack <int> s;
int color[N_MAX + 10], cnt[N_MAX + 10];

int in[N_MAX + 10];
queue <int> q;
int w[N_MAX + 10], dp[N_MAX + 10]; // w[i]表示大点i的权值

{
g[x].push_back(y);
}

void tarjan(int x)
{
dfn[x] = low[x] = ++now;
ins[x] = true;
s.push(x);
for (int i = 0; i < (int) g[x].size(); i++) {
int y = g[x][i];
if (dfn[y] == 0) tarjan(y), low[x] = min(low[x], low[y]);
else if (ins[y]) low[x] = min(low[x], dfn[y]);
}
if (low[x] != dfn[x]) return;
color[x] = ++color[0];
cnt[color[0]]++;
while (s.top() != x) {
int y = s.top();
color[y] = color[0];
ins[y] = false;
s.pop();
cnt[color[0]]++;
}
ins[x] = false;
s.pop();
}

void resetPoint()
{
for (int i = 1; i <= n; i++)
if (dfn[i] == 0) tarjan(i);
memset(g, 0, sizeof(g)); // 重置所有的边
for (int i = 1; i <= m; i++) {
int x = color[u[i]], y = color[v[i]];
if (x != y) addEdge(x, y);
}
}

int topSort()
{
for (int x = 1; x <= color[0]; x++)
for (int i = 0; i < (int) g[x].size(); i++)
in[g[x][i]]++;
for (int i = 1; i <= color[0]; i++)
if (in[i] == 0) dp[i] = w[i], q.push(i);
int ans = 0;
while (!q.empty()) {
int x = q.front();
q.pop();
ans = max(ans, dp[x]);
for (int i = 0; i < (int) g[x].size(); i++) {
int y = g[x][i];
dp[y] = max(dp[y], dp[x] + w[y]);
if (--in[y] == 0) q.push(y);
}
}
return ans;
}

int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= m; i++) {
scanf("%d%d", &u[i], &v[i]);
}
resetPoint();
for (int i = 1; i <= n; i++)
w[color[i]] += a[i];
printf("%d\n", topSort());
return 0;
}


©️2019 CSDN 皮肤主题: 精致技术 设计师: CSDN官方博客