当前位置:网站首页>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;
}
边栏推荐
猜你喜欢

找工作必备!如何让面试官对你刮目相看,建议收藏尝试!!

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

Today's sleep quality record 74 points

威纶通触摸屏如何打开并升级EB8000旧版本项目并更换触摸屏型号?

求解多元多次方程解的个数

KMP 字符串匹配问题

Uses of Anacoda

Analysis of the development trend of game metaverse

scikit-learn no moudule named six

教你VSCode如何快速对齐代码、格式化代码
随机推荐
【建议收藏】ヾ(^▽^*)))全网最全输入输出格式符整理
AI应用第一课:支付宝刷脸登录
JS prototype hasOwnProperty in 加方法 原型终点 继承 重写父类方法
Based on php online learning platform management system acquisition (php graduation design)
2022 edition of MySQL tutorial, top collection good, take your time
Unity Shader general lighting model code finishing
AQS
LeetCode952三部曲之二:小幅度优化(137ms -> 122ms,超39% -> 超51%)
【Verilog刷题篇】硬件工程师从0到入门1|基础语法入门
shell programming conventions and variables
今日睡眠质量记录74分
模拟数据之mockjs
将vim与系统剪贴板的交互使用
[深入研究4G/5G/6G专题-48]: 5G Link Adaption链路自适应-4-下行链路自适应DLLA-PDCCH信道
高等代数_证明_矩阵的行列式为特征值之积, 矩阵的迹为特征值之和
易周金融分析 | 银行ATM机智能化改造提速;互联网贷款新规带来挑战
Recycling rental system 100% open source without encryption Mall + recycling + rental
【C语言】猜数字小游戏
力扣第 304 场周赛复盘
小程序毕设作品之微信体育馆预约小程序毕业设计成品(4)开题报告