当前位置:网站首页>Graph Theory - Strongly Connected Component Condensation + Topological Sort
Graph Theory - Strongly Connected Component Condensation + Topological Sort
2022-08-01 22:07:00 【ThXe】
Tarjan算法是一种用于查找已知图中的强连通分量的方法
时间复杂度:O(n+m)//n为点数,m为边数
解法一:并查集维护
#include<bits/stdc++.h>
using namespace std;
#define N 100010
struct edge{
int u, v, nxt;
}e[N];
queue <int> q;
int head[N], cnt, n, m, x, y, vis[N], f[N], c[N], s[N], r[N], ans = 1, W[N];
inline void add(int u, int v){
e[++cnt].u = u;//注意要把 u 也给加上,后面需要调用
e[cnt].v = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
int anc(int x){
if(x == f[x]) return x;
return f[x] = anc(f[x]);
}//并查集模板
void dfs(int u){
for(int i = head[u]; i; i = e[i].nxt){
int v = e[i].v;
if(!vis[v]){
//如果没搜索
vis[v] = vis[u] + 1;//记录“深度”
dfs(v);//继续搜
}
int fu = anc(u), fv = anc(v);//anc is the union function
if(vis[fv] > 0){
//Must be in search
if(vis[fu] < vis[fv]) f[fv] = fu;
else f[fu] = fv;//注意这里,The depth is small for the father
}
}
vis[u] = -1;//mark search done
return;
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) f[i] = i, scanf("%d", W + i);
for(int i = 1; i <= m; ++i){
scanf("%d%d", &x, &y);
add(x, y);
}
for(int i = 1; i <= n; ++i){
if(!vis[i]){
//If this point has not been searched, continue to search
vis[i] = 1;
dfs(i);
}
}
for(int i = 1; i <= n; ++i) c[anc(i)] += W[i];//Reduced point weight processing
memset(head, 0, sizeof(head));
cnt = 0;//Here to clear-v-
for(int i = 1; i <= m; ++i){
x = f[e[i].u], y = f[e[i].v];//Since it has all been traversed above anc 函数了,这里直接调用即可
if(x != y) add(x, y), r[y]++;//Do not connect edges without a strongly connected component
}
for(int i = 1; i <= n; ++i){
if(i == f[i] && !r[i]) q.push(i), s[i] = c[i];
}//s[i] 是 dp 数组
while(!q.empty()){
int u = q.front(); q.pop();
for(int i = head[u]; i; i = e[i].nxt){
int v = e[i].v;
s[v] = max(s[v], s[u] + c[v]);
if(--r[v] == 0) q.push(v);
}
ans = max(ans, s[u]);
}//toposort 模板
printf("%d", ans);
return 0;
}
tarjan 缩点
#include<bits/stdc++.h>
using namespace std;
const int maxn = 10000 + 15;
int n, m, idx, tim, top, s;
int p[maxn], head[maxn], Scc_id[maxn], dfn[maxn], low[maxn];
//DFN(u)为节点uThe sequence number when the search was found(时间戳),Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号
//Scc_idis which strongly connected component the final node belongs to,Scc_id[y]=1,则y节点为1Points in the strongly connected components
//p最终为Scc总权值
int stac[maxn], vis[maxn];//The stack is only used to indicate whether there is a parent-child relationship at this time
int h[maxn], in[maxn], dist[maxn];
struct EDGE
{
int to; int next; int from;
}edge[maxn * 10], ed[maxn * 10];//原图、新图
void add(int x, int y)
{
edge[++idx].next = head[x];
edge[idx].from = x;
edge[idx].to = y;
head[x] = idx;
}
void tarjan(int x)
{
low[x] = dfn[x] = ++tim;
stac[++top] = x; vis[x] = 1;
for (int i = head[x]; i; i = edge[i].next)
{
int v = edge[i].to;
if (!dfn[v]) {
tarjan(v);
low[x] = min(low[x], low[v]);
}
else if (vis[v])
{
low[x] = min(low[x], low[v]);
}
}
if (dfn[x] == low[x])
{
int y;
while (y = stac[top--])
{
Scc_id[y] = x;
vis[y] = 0;
if (x == y) break;
p[x] += p[y];
}
}
}
int topo()
{
queue <int> q;
int tot = 0;
for (int i = 1; i <= n; i++)
if (Scc_id[i] == i && !in[i])
{
q.push(i);//The strongly connected component root node and in-degree is 0的节点入队
dist[i] = p[i];//dist为dp数组,以下标为iThe maximum weight of the point
}
while (!q.empty())
{
int k = q.front(); q.pop();
for (int i = h[k]; i; i = ed[i].next)
{
int v = ed[i].to;
dist[v] = max(dist[v], dist[k] + p[v]);
in[v]--;
if (in[v] == 0) q.push(v);
}
}
int ans = 0;
for (int i = 1; i <= n; i++)
ans = max(ans, dist[i]);
return ans;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &p[i]);
for (int i = 1; i <= m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
}
for (int i = 1; i <= n; i++)
if (!dfn[i]) tarjan(i);
for (int i = 1; i <= m; i++)
{
int x = Scc_id[edge[i].from], y = Scc_id[edge[i].to];
if (x != y)//如果xyDoes not belong to a strong connectivity component,Edges are required
{
ed[++s].next = h[x];ed[s].to = y;ed[s].from = x;//add(x,y) s为新idx
h[x] = s;in[y]++;
}
}
printf("%d", topo());
return 0;
}
边栏推荐
- 深度学习Course2第一周Practical aspects of Deep Learning习题整理
- Based on php tourism website management system acquisition (php graduation design)
- leetcode 204. Count Primes 计数质数 (Easy)
- feel so stupid
- Still struggling with reporting tool selection?To take a look at this
- 易周金融分析 | 银行ATM机智能化改造提速;互联网贷款新规带来挑战
- VGUgarbage collector(垃圾回收器)的实现原理
- Postman 批量测试接口详细教程
- Analysis of the development trend of game metaverse
- 小程序毕设作品之微信体育馆预约小程序毕业设计成品(1)开发概要
猜你喜欢

SAP ABAP OData 服务如何支持删除(Delete)操作试读版

程序员必备的 “ 摸鱼神器 ” 来了 !

No more rolls!After joining ByteDance for a week, he ran decisively.

小程序毕设作品之微信体育馆预约小程序毕业设计成品(3)后台功能

Getting Started Database Days4

统计单词数

网络水军第一课:手写自动弹幕

【Verilog刷题篇】硬件工程师从0到入门1|基础语法入门

如何给 UE4 场景添加游戏角色

Based on php hotel online reservation management system acquisition (php graduation project)
随机推荐
【建议收藏】ヾ(^▽^*)))全网最全输入输出格式符整理
深度学习Course2第一周Practical aspects of Deep Learning习题整理
不卷了!入职字节跳动一周就果断跑了。
Ten years after graduation, financial freedom: those things that are more important than hard work, no one will ever teach you
How to prevent governance attacks in DAOs?
(翻译)按钮的对比色引导用户操作的方式
shell specification and variables
解决 win10 下 ISE14.7的 iMPACT 崩溃问题 - FPGA 笔记
Dichotomy Medium LeetCode6133. Maximum Number of Groups
_ _ determinant of a matrix is higher algebra eigenvalue of the product, the characteristic value of matrix trace is combined
AQS
Based on php animation peripheral mall management system (php graduation design)
联邦学习的框架搭建
365天挑战LeetCode1000题——Day 046 生成每种字符都是奇数个的字符串 + 两数相加 + 有效的括号
Kubernetes Scheduler全解析
感觉自己好傻
Raspberry Pi information display small screen, display time, IP address, CPU information, memory information (C language), four-wire i2c communication, 0.96-inch oled screen
shell规范与变量
工程建筑行业数据中台指标分析
Advanced Algebra_Proof_The algebraic multiplicity of any eigenvalue of a matrix is greater than or equal to its geometric multiplicity