洛谷 P1726:上白泽慧音 ← Tarjan算法

【题目来源】
https://www.luogu.com.cn/problem/P1726

【题目描述】
在幻想乡,上白泽慧音是以知识渊博闻名的老师。春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄。因此慧音决定换一个能够聚集最多人数的村庄作为新的教学地点。
人间之里由
N 个村庄(编号为 1⋯N)和 M 条道路组成,道路分为两种一种为单向通行的,一种为双向通行的,分别用 1 和 2 来标记。如果存在由村庄 A 到达村庄 B 的通路,那么我们认为可以从村庄 A 到达村庄 B,记为 (A,B)。当 (A,B) 和  (B,A) 同时满足时,我们认为 A,B 是绝对连通的,记为 〈A,B〉。绝对连通区域是指一个村庄的集合,在这个集合中任意两个村庄 X,Y 都满足 〈X,Y〉。现在你的任务是,找出最大的绝对连通区域,并将这个绝对连通区域的村庄按编号依次输出。若存在两个最大的,输出字典序最小的,比如当存在 1,3,4 和 2,5,6 这两个最大连通区域时,输出的是 1,3,4。

【输入格式】
第一行共两个正整数 N,M。
第 2 行至第 M+1 行,每行有三个正整数 a,b,t。若
t=1 则表示存在从村庄 a 到 b 的单向道路,若 t=2 表示村庄 a,b 之间存在双向通行的道路。保证每条道路只出现一次。

【输出格式】
第一行输出 1 个整数,表示最大的绝对连通区域包含的村庄个数。
第二行输出若干个整数,依次输出最大的绝对连通区域所包含的村庄编号。

【输入样例】
5 5
1 2 1
1 3 2
2 4 2
5 1 2
3 5 1

【输出样例】
3
1 3 5

【说明/提示】
对于 60% 的数据,1≤N≤200,且 0≤M≤10^4;
对于 100% 的数据,
1≤N≤5×10^3,且 0≤M≤5×10^4

【算法分析】
● Tarjan算法简介
Tarjan算法是一个基于深搜(DFS),用于求解图中
强连通分量(SCC)割点/割边问题的算法。
Tarjan算法在搜索的过程中,会形成一棵
搜索树

由上图易知,横向边和前向边都无法构成回路,即不能形成大于一个点的强连通分量。所以,在本题中应用 Tarjan 算法的关键,就是找出重要的后向边,用于求解图中的强连通分量。

● Tarjan算法中两个核心数组
dfn[x]low[x]
dfn[x]:表示一个结点的时间戳。时间戳是在 dfs 的过程中,每个结点第一次被访问的时间顺序。
low[x]:表示一个结点的追溯值。追溯值是一个结点通过后向边能够回到的最早结点的编号,也就是 dfn 的最小值
dfn 可以通过两种方式更新:
(1)若在搜索树上 x 是 y 的父结点,那么 low[x]=min(low[x],low[y])
(2)若是
非树边(横向边、后向边),那么 low[x]=min(low[x],dfn[y])
要注意的是,
在无向图中,儿子到父亲的那条边不处理,要不然 low 值就都是 1 了,没有意义。

● Tarjan算法关于图中强连通分量的
判定条件
与当前点 cur 关联的所有边都被遍历完之后,判断它的 dfn 是否等于 low(即,dfn[cur] == low[cur])?若为 True,则表示搜到了一个强连通分量的根。之后,出栈,直到当前结点 cur 终止。出栈的都是这个强连通分量集合内的结点;若为 False,回溯。

● 本题可考虑使用
优先队列实现按字典序输出结果。
优先队列:
https://blog.csdn.net/qq_19656301/article/details/82490601

#include <bits/stdc++.h>
using namespace std;priority_queue<int,vector<int>,less<int> > down;
priority_queue<int,vector<int>,greater<int> > up;int main() {int n,x;cin>>n;while(n--) {cin>>x;down.push(x);up.push(x);}while(!down.empty()) {cout<<down.top()<<" ";down.pop();}cout<<endl;while(!up.empty()) {cout<<up.top()<<" ";up.pop();}return 0;
}/*
in:
5
6 9 2 7 1out:
9 7 6 2 1
1 2 6 7 9
*/

● 链式前向星:https://blog.csdn.net/hnjzsyjyj/article/details/139369904
val[idx]:存储编号为 idx 的边的值 
e[idx]:存储编号为 idx 的结点的值
ne[idx]:存储编号为 idx 的结点指向的结点的编号
h[a]:存储头结点 a 指向的结点的编号

【算法代码一】

#include <bits/stdc++.h>
using namespace std;const int maxn=5e3+5;
vector<int> g[maxn];
stack<int> stk;
int scc[maxn]; //scc[i]:第i个强连通分量的结点数
int cnt_scc;
int dfn[maxn]; //dfn[i]:结点i的时间戳
int low[maxn]; //low[i]:结点i的追溯值。也就是dfn的最小值。
int vis[maxn];
int cnt[maxn];
int ts; //时间戳 timestampvoid tarjan(int u) {dfn[u]=low[u]=++ts;stk.push(u);vis[u]=1;for(int t:g[u]) {if(dfn[t]==0) {tarjan(t);low[u]=min(low[u],low[t]);} else if(vis[t]) {low[u]=min(low[u],low[t]);}}if(low[u]==dfn[u]) {cnt_scc++;while(stk.top()!=u) {int t=stk.top();vis[t]=0;scc[t]=cnt_scc;cnt[cnt_scc]++;stk.pop();}scc[u]=cnt_scc;stk.pop();vis[u]=0;cnt[cnt_scc]++;}
}int main() {int n,m;cin>>n>>m;for(int i=1; i<=m; i++) {int x,y,op;cin>>x>>y>>op;g[x].push_back(y);if(op==2) g[y].push_back(x);}for(int i=1; i<=n; i++) {if(!dfn[i]) tarjan(i);}int t=0, ans=-1;for(int i=1; i<=n; i++) {if(ans<cnt[scc[i]]) {ans=cnt[scc[i]];t=scc[i];}}cout<<ans<<endl;int cur=0;for(int i=1; i<=n; i++) {if(scc[i]==t) {if(cur++) cout<<" ";cout<<i;}}cout<<endl;return 0;
}/*
in:
5 5
1 2 1
1 3 2
2 4 2
5 1 2
3 5 1out:
3
1 3 5
*/


【算法代码二】

#include <bits/stdc++.h>
using namespace std;const int maxn=5e5+5;
const int inf=0x3f3f3f3f;int dfn[maxn]; //dfn[i]:结点i的时间戳
int low[maxn]; //low[i]:结点i所能到达的最小时间戳
int lie[maxn]; //lie[i]:结点i位于的强联通分量
int siz[maxn]; //siz[i]:第i个强联通分量的结点数
int stk[maxn]; //模拟栈
int top; //栈顶
int tot; //第tot个强联通分量
int ts; //时间戳 timestamp
int ans=-inf;
int n,m;int e[maxn<<1],ne[maxn<<1],h[maxn],idx;
void add(int a,int b) {e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}void tarjan(int u) {dfn[u]=low[u]=++ts;stk[++top]=u;for(int i=h[u]; ~i; i=ne[i]) {int v=e[i];if(!dfn[v]) {tarjan(v);low[u]=min(low[u],low[v]);} else if(!lie[v]) low[u]=min(low[u],dfn[v]);}if(low[u]==dfn[u]) {lie[u]=++tot;siz[tot]++;while(stk[top]!=u) {siz[tot]++;lie[stk[top]]=tot;top--;}top--;}
}int main() {memset(h,-1,sizeof(h));cin>>n>>m;for(int i=1; i<=m; i++) {int x,y,f;cin>>x>>y>>f;if(f==1) add(x,y);if(f==2) add(x,y),add(y,x);}for(int i=1; i<=n; i++) {if(!dfn[i]) tarjan(i);}for(int i=1; i<=tot; i++) ans=max(ans,siz[i]);cout<<ans<<endl;for(int i=1; i<=n; i++) {if(siz[lie[i]]==ans) {int cur=lie[i];for(int j=i; j<=n; j++) {if(lie[j]==cur) cout<<j<<" ";}return 0;}}return 0;
}/*
in:
5 5
1 2 1
1 3 2
2 4 2
5 1 2
3 5 1out:
3
1 3 5
*/




【参考文献】
https://www.cnblogs.com/dgsvygd/p/16579748.html
https://www.cnblogs.com/bloodstalk/p/17432793.html
https://blog.csdn.net/yikeyoucaihua/article/details/135832822
https://www.luogu.com.cn/problem/solution/P1726
https://www.luogu.com.cn/article/6dgk1yk1
https://blog.csdn.net/qq_30277239/article/details/118683637
https://zhuanlan.zhihu.com/p/161537289




 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/30274.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

redis复习

redis知识点 redis持久化redis 订阅发布模式redis主从复制哨兵模式redis雪崩&#xff0c;穿透缓存击穿&#xff08;请求太多&#xff0c;缓存过期&#xff09;缓存雪崩 redis持久化 redis是内存数据库&#xff0c;持久化有两种方式&#xff0c;一种是RDB&#xff08;redis dat…

【计算机网络】[第4章 网络层][自用]

1 概述 (1)因特网使用的TCP/IP协议体系(四层)的网际层,提供的是无连接、不可靠的数据报服务; (2)ATM、帧中继、X.25的OSI体系(七层)中的网络层,提供的是面向连接的、可靠的虚电路服务。 (3)路由选择分两种: 一种是由用户or管理员人工进行配置(只适用于规…

图解Linux内核(基于6.x):解读Linux内存反向映射之匿名映射

文章目录 &#x1f4d1;前言一、匿名映射的mapping二、推荐阅读2.1 一图速览2.2 内容简介 &#x1f4d1;前言 内存映射中&#xff0c;我们经常讨论的是由虚拟内存定位物理内存&#xff08;也就是folio或者page&#xff09;&#xff0c;实际上在很多场景中&#xff08;比如内存回…

linux写代码环境和工具

基础指令 目录 前言 二、yum工具的使用 1.yum是什么&#xff1f; 2.查看软件包 3.配置sudo 4.如何卸载软件 三、vim的使用 1. vim的基本概念 2. vim的基本操作 3. vim正常模式命令集 4.简单vim配置 四、Linux编译器-gcc/g使用 1、格式 2、gcc选项 3.gcc/g工作和…

Vue CLI,Vue Router,Vuex

前言 Vue CLI、Vue Router 和 Vuex 都是 Vue.js 生态系统中的重要组成部分&#xff0c;它们在构建 Vue 应用程序时扮演着关键角色。 Vue CLI Vue CLI 介绍 Vue CLI 是 Vue.js 的官方命令行工具&#xff0c;用于快速搭建 Vue.js 项目。它提供了一个图形界面&#xff08;通过…

工程打包与运行

黑马程序员Spring Boot2 文章目录 先点击cean&#xff0c;确保打包之前是个干净的环境点击package进行打包&#xff0c;打包成功之后可以看到target文件夹下的文件 到项目目录下使用终端打开&#xff0c;并使用以下命令运行打包好的程序 如果遇到没有主清单属性的问题&#xff…

搜维尔科技邀您共赴2024第四届轨道车辆工业设计国际研讨会

会议内容 聚焦“创新、设计、突破”&#xff0c;围绕“面向生命健康、可持续发展的轨道交通系统” 为主题&#xff0c;从数字化、智能化、人性化、绿色发展等方面&#xff0c;探索轨道交通行业的设计新趋势及发展新机遇。 举办时间 2024年7月10日-12日 举办地点 星光岛-青岛融…

5.音视频基础 FLV

目录 简说FLV FLV Header FLV Body Tag Header ​编辑Tag Data Audio Data Video Data Script Data 简说FLV FLV格式可以包含音频、视频和文本数据&#xff0c;并且可以在网络上进行流媒体传输。优点是文件大小较小&#xff0c;压缩效率高&#xff0c;并且可以在较低…

WiFi/BLE芯片(1):英飞凌

前言: 大部分客户很少直接接触到WiFi/Bluetooth的芯片,一般是直接封装到了模块中,隔了一层。具体到芯片而言,WiFi/BLE芯片,芯片厂家有:Qualcomm高通、broadcom博通、Infineon英飞凌、Nordic诺迪科、Espressof乐鑫等。而英飞凌这块产品也是很丰富的,低功耗、距离等性能指…

飞创直线模组厂家,为高精度运动系统提供直驱技术解决方案

飞创Faster motion是国内一家专业的直线模组厂家&#xff0c;致力于研发、设计、生产超长行程、超高速度、超高精度、超重负载以及速度平稳的单轴和多轴直线电机模组&#xff0c;为高速、高精度运动平台提供直驱技术解决方案。 飞创直线模组其生产的单轴、双轴、龙门、多轴模组…

化工电力系统RFID无线测温技术的重要性。

在现代工业体系中&#xff0c;化工电力系统的安全与效率对于整个生产链的顺畅运行至关重要。在日常工作中,由于设备制造的原因,设备受环境污染的原因、设备长期运行、严重超载运行、触点氧化、电弧冲击等原因造接触电阻增大,因此在运行时往往不断发热,温度不断上升,给设备安全运…

Leetcode Hot100之双指针

1. 移动零 题目描述 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。解题思路 双指针遍历一遍即可解决: 我们定义了两个指针 i 和 j&#xf…

C++ Windows Hook使用

GitHub - microsoft/Detours: Detours is a software package for monitoring and instrumenting API calls on Windows. It is distributed in source code form. /*挂载钩子 setdll /d:C:\Users\g\source\repos\LotTest\Release\lotDll.dll C:\Users\g\source\repos\LotTest…

Java特性之设计模式【访问者模式】

一、访问者模式 概述 在访问者模式&#xff08;Visitor Pattern&#xff09;中&#xff0c;我们使用了一个访问者类&#xff0c;它改变了元素类的执行算法。通过这种方式&#xff0c;元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式&…

WPF三方UI库全局应用MessageBox样式(.NET6版本)

一、问题场景 使用HandyControl简写HC 作为基础UI组件库时&#xff0c;希望系统中所有的MessageBox 样式都使用HC的MessageBox&#xff0c;常规操作如下&#xff1a; 在对应的xxxx.cs 顶部使用using 指定特定类的命名空间。 using MessageBox HandyControl.Controls.Message…

js语法---理解反射Reflect对象和代理Proxy对象

Reflect 基本要点 反射&#xff1a;reflect是一个内置的全局对象&#xff0c;它的作用就是提供了一些对象实例的拦截方法&#xff0c;它的用法和Math对象相似&#xff0c;都只有静态方法和属性&#xff0c;同时reflect也没有构造器&#xff0c;无法通过new运算符构建实例对象&…

xcode和iPhone真机或者watch真机连接问题

1.如果真机是第一次连接xocde&#xff0c;就需要开启真机上的开发者模式&#xff0c;开启开发者模式的方式&#xff1a; iphone/ipad开启方式: 设置 > 隐私与安全 > 开发者模式 > 开启&#xff0c;然后重启就可以了 watch设置&#xff1a;很麻烦&#xff0c;看文章…

现代谱估计分析信号的功率谱(1)---AR 模型谱估计

本篇文章是博主在通信等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对通信等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在通信领域笔记&#xff1a;…

进阶篇06——锁

概述 全局锁 表级锁 表锁 元数据锁 元数据锁是系统自动加的&#xff0c;不需要我们手动执行命令添加。 意向锁 意向锁和元数据锁一样&#xff0c;也是在加行锁的时候自动给表加上相应的意向锁&#xff0c;不需要我们手动添加。 行级锁 行锁 读锁和读锁兼容&#xff0c;写锁…

易舟云财务软件:开启云记账新时代

在数字化浪潮的推动下&#xff0c;财务管理正经历着深刻的变革。易舟云财务软件&#xff0c;作为一款引领时代的云记账平台&#xff0c;以其卓越的功能和便捷的操作&#xff0c;为企业带来了全新的财务管理体验。 云记账&#xff0c;财务管理的未来趋势 云记账&#xff0c;即基…