当前位置: 首页 > news >正文

Tarjan算法总结

强联通分量

点击查看代码
#include<bits/stdc++.h>using namespace std;int n,m;
vector<int> e[10005];int dfn[10005],low[10005],timtp;
int stk[10005],stktp;
bool instk[10005];
int scccnt,inscc[10005];
vector<int> scc[10005];
bool vis[10005];void tarjan(int x){dfn[x] = low[x] = ++timtp;stk[++stktp] = x;instk[x] = 1;for(auto y:e[x]){if(!dfn[y]){tarjan(y);low[x] = min(low[x],low[y]);}else if(instk[y]) low[x] = min(low[x],dfn[y]);}if(low[x] >= dfn[x]){scccnt++;int y;do{y = stk[stktp--];instk[y] = 0;inscc[y] = scccnt;scc[scccnt].push_back(y);}while(y != x);}}signed main(){cin >> n >> m;for(int i = 1;i <= m;++ i){int u,v;cin >> u >> v;e[u].push_back(v);}for(int i = 1;i <= n;++ i)if(!dfn[i]) tarjan(i);cout << scccnt << endl;for(int i = 1;i <= n;++ i){if(vis[inscc[i]]) continue;vis[inscc[i]] = 1;int w = inscc[i];sort(scc[w].begin(),scc[w].end());for(auto x:scc[w]) cout << x << " ";cout << endl;}return 0;}

缩点

点击查看代码
#include<bits/stdc++.h>#define int long longusing namespace std;int n,m;
int a[10005];
struct bian{int u,v;
}b[100005];
vector<int> e[10005];
vector<int> e2[10005];
int a2[10005];int dfn[10005],low[10005],timtp;
int stk[10005],stktp;
int instk[10005];
int beinscc[10005];
int cntscc;
int sizscc[10005];void dfs(int x){dfn[x] = low[x] = ++timtp;stk[++stktp] = x;instk[x] = 1;for(auto y:e[x]){if(!dfn[y]){dfs(y);low[x] = min(low[x],low[y]);}else if(instk[y]) low[x] = min(low[x],dfn[y]);}if(low[x] == dfn[x]){cntscc++;int y;do{y = stk[stktp--];instk[y] = 0;sizscc[cntscc] += a[y];beinscc[y] = cntscc;}while(y != x);}}int ind[10005];
int ds[10005];signed main(){cin >> n >> m;for(int i = 1;i <= n;++ i)cin >> a[i];for(int i = 1;i <= m;++ i){int u,v;cin >> u >> v;b[i] = {u,v};e[u].push_back(v);}for(int i = 1;i <= n;++ i)if(!dfn[i]) dfs(i);for(int i = 1;i <= m;++ i){if(beinscc[b[i].u] != beinscc[b[i].v]){int u = beinscc[b[i].u];int v = beinscc[b[i].v];e2[u].push_back(v);ind[v]++;}}for(int i = 1;i <= cntscc;++ i)a2[i] = sizscc[i];queue<int> q;for(int i = 1;i <= cntscc;++ i)if(ind[i] == 0) ds[i] = a2[i],q.push(i);while(!q.empty()){int x = q.front();q.pop();for(auto y:e2[x]){ds[y] = max(ds[y],a2[y]+ds[x]);ind[y]--;if(!ind[y]) q.push(y);}}int ans = 0;for(int i = 1;i <= cntscc;++ i)ans = max(ans,ds[i]);cout << ans;return 0;}

割点

点击查看代码
#include<bits/stdc++.h>using namespace std;int n,m;
vector<int> e[20005];int dfn[20005],low[20005],timtp;
int gdcnt,isgd[20005];void tarjan(int x,int com){dfn[x] = low[x] = ++timtp;int child = 0;for(auto y:e[x]){if(!dfn[y]){tarjan(y,com);low[x] = min(low[x],low[y]);child++;if(low[y] >= dfn[x]&&x != com)gdcnt += (!isgd[x]),isgd[x] = 1;}else low[x] = min(low[x],dfn[y]);}if(x == com&&child >= 2) gdcnt += (!isgd[x]),isgd[x] = 1;}signed main(){cin >> n >> m;for(int i = 1;i <= m;++ i){int u,v;cin >> u >> v;e[u].push_back(v);e[v].push_back(u);}for(int i = 1;i <= n;++ i)if(!dfn[i]) tarjan(i,i);cout << gdcnt << endl;for(int i = 1;i <= n;++ i)if(isgd[i]) cout << i << " ";return 0;}

点双联通分量

点击查看代码
#include<bits/stdc++.h>using namespace std;int n,m;
vector<int> e[500005];int dfn[500005],low[500005],timtp;
int stk[500005],stktp;
int scccnt;
vector<int> scc[500005];void tarjan(int x,int root){dfn[x] = low[x] = ++timtp;stk[++stktp] = x;int child = 0;for(auto y:e[x]){if(!dfn[y]){tarjan(y,root);low[x] = min(low[x],low[y]);if(low[y] >= dfn[x]){scccnt++;int w;do{w = stk[stktp--];scc[scccnt].push_back(w);}while(w != y);scc[scccnt].push_back(x);}child++;}else low[x] = min(low[x],dfn[y]);}if(x == root&&child == 0)scc[++scccnt].push_back(x);}signed main(){cin >> n >> m;for(int i = 1;i <= m;++ i){int u,v;cin >> u >> v;e[u].push_back(v);e[v].push_back(u);}for(int i = 1;i <= n;++ i)if(!dfn[i]) stktp = 0,tarjan(i,i);cout << scccnt << endl;for(int i = 1;i <= scccnt;++ i){cout << scc[i].size() << " ";for(auto x:scc[i]) cout << x << " ";cout << endl;}return 0;}

边双联通分量

点击查看代码
#include<bits/stdc++.h>using namespace std;int n,m,w_wo_o;
vector<pair<int,int> > e[500005];int dfn[500005],low[500005],timtp;
int scccnt;
vector<int> scc[500005];
int stk[500005],stktp;void tarjan(int x,int com){dfn[x] = low[x] = ++timtp;stk[++stktp] = x;for(auto [y,whe]:e[x]){if(!dfn[y]){tarjan(y,whe);low[x] = min(low[x],low[y]);}else if(whe != (com^1)) low[x] = min(low[x],dfn[y]);}if(low[x] == dfn[x]){scccnt++;int w;do{w = stk[stktp--];scc[scccnt].push_back(w);}while(w != x);}}signed main(){cin >> n >> m;for(int i = 1;i <= m;++ i){int u,v;cin >> u >> v;e[u].push_back({v,w_wo_o++});e[v].push_back({u,w_wo_o++});}for(int i = 1;i <= n;++ i)if(!dfn[i]) stktp = 0,tarjan(i,-1);cout << scccnt << endl;for(int i = 1;i <= scccnt;++ i){cout << scc[i].size() << " ";for(auto x:scc[i]) cout << x << " ";cout << endl;}return 0;}
http://www.jsqmd.com/news/50863/

相关文章:

  • 【CV】【IRSRMamba】basicSR库
  • 2025年11月十大效果图公司推荐榜单:专业分析与权威评测对比
  • 2025 年 11 月管道更換服務權威推薦榜:專業施工與高效維修,涵蓋老舊破損無縫防腐耐高溫管道更換,包括自來水消防燃氣排水污水工業通風等各類室內外場景
  • L12_自定义接口与权限验证_从零开始
  • python environment settings
  • 2025 年 11 月靶材廠家權威推薦榜:濺射/磁控濺射/旋轉靶材,ITO/半導體/光學鍍膜,陶瓷/金屬/鈦/鋁/銅/鎢/鉬/鉭/矽/合金/稀土靶材精選,工藝精湛與創新應用深度解析
  • 2025 年 11 月高壓清洗服務廠家推薦排行榜,管道/下水道/污水管/市政管道高壓清洗,化糞池/隔油池/污水池專業清洗,家庭/商鋪/小區/工廠高效深度清潔首選!
  • 如何在C++中实现面向对象编程?
  • 一物一码赋能全链路管控,二脉科技互动溯源系统引领行业新生态 !
  • 最简单的畅通工程
  • 高级程序语言设计第七次
  • 有限元技巧核心原理与学习路径:从一维基础到多维拓展(七步流程)
  • 实用指南:面向高并发场景的舆情处置技术实践——基于字节探索Infoseek的架构拆解
  • Day48(18)-F:\硕士阶段\Java\课程代码\后端\web-ai-code\web-ai-project02\tlias-web-management
  • 习题解析之:模拟生成微软序列号
  • 50046_基于微信小程序的电影票预订管理系统
  • Verilog位宽赋值规则
  • 云栖实录|驰骋在数据洪流上:Flink+Hologres驱动零跑科技实时计算的应用与实践 - 指南
  • 重练算法(代码随想录版) day21 - 二叉树part8
  • 第四十八篇
  • 2025年11月最新出炉!南京装修公司推荐首推欧阅恒装 TOP5权威榜单
  • 细微颗粒布满了整个房间 点燃通向毁灭实验的导线
  • 漏洞赏金猎人的深度侦察方法:内容发现进阶指南
  • 完整教程:【2025最全】国内AIPPT工具排行榜
  • i.MX 6ULL复位管脚
  • Django 用户认证流程详解:从原理到搭建
  • 棋盘 就是最简单的nim
  • [豪の算法奇妙冒险] 代码随想录算法训练营第六天 | 242-有效的字母异位词、349-两个数组的交集、202-快乐数、1-两数之和
  • 会不会是遗嘱呢……
  • 关于powershell中的-哈希表-Hashtable-类型-说明-类似于python中的字典