Light OJ - 1026 - Critical Links(图论-Tarjan算法求无向图的桥数) - 带详细注释
无向连通图中,如果删除某边后,图变成不连通,则称该边为桥。
也可以先用Tajan()进行dfs算出所有点 的low和dfn值,并记录dfs过程中每个 点的父节点;然后再把所有点遍历一遍, 看其low和dfn,满足dfn[ fa ]<low[ i ](0<i<=n, i 的 father为fa) —— 则桥为fa-i。 找桥的时候,要注意看有没有重边;有重边,则不是桥。
另外,本题的题意及测试样例中没有重边,所以不用考虑重边。
带详细注释的题解:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<stack>
#include<vector>
#define maxn 10010
using namespace std;
int dfn[maxn],low_link[maxn] ,Father[maxn];
//tarjan 算法的dfn ——在DFS过程中 的访问序号(也可以叫做开始时间
//tarjan 算法的low_link[i]——从i节点出发DFS过程中i下方节点所能到达的最早的节点的 开始时间
int bridgenum, Time ,n ; //桥的总数,dfn时间戳,n为顶点数,
vector<int>G[maxn]; //定义图的邻接矩阵表
stack<int>st;
struct node{
int u,v;
}bridge[maxn]; //整个图的桥的存储
bool cmp( node a,node b )
{
if(a.u!=b.u)return a.u<b.u;
else return a.v<b.v;
}
void init(){
int i;
for(i=;i<=n;i++) //初始化邻接表
G[i].clear();
bridgenum=;Time=;
memset(dfn,,sizeof(dfn));
memset(low_link,,sizeof(low_link));
memset(Father,,sizeof(Father));
}
void tarjan(int u,int fa)
{
low_link[u]=dfn[u]=++Time;
Father[u]=fa; //记录父节点
// st.push(u);
for(int i=;i<(int)G[u].size();i++){
int v=G[u][i];
if(!dfn[v]){
tarjan(v,u);
low_link[u]=min(low_link[u],low_link[v]);
}
else if(v!=fa){ //不能连接到父节点!
low_link[u]=min(low_link[u],dfn[v]);
}
else{
//这种情况就是有重边的情况!不予处理,直接跳过!
}
}
}
void solve()
{
for(int i=;i<n;i++){
if(!dfn[i])
tarjan(i,-);
}
int ans=;
for(int i=;i<n;i++){
int v=Father[i];
if(dfn[v]<low_link[i]&&v!=-){ //若v-i可以构成父节点
bridge[ans].u=v; //桥的两条边
bridge[ans].v=i;
if(bridge[ans].u>bridge[ans].v)
swap(bridge[ans].u,bridge[ans].v);
ans++;
}
}
sort(bridge,bridge+ans,cmp);
printf("%d critical links\n",ans);
for(int i=;i<ans;i++){
printf("%d - %d\n",bridge[i].u,bridge[i].v);
}
}
int cal_num(char ch[]){
int len=strlen(ch),s=;
for(int i=;i<=len-;i++){
s=s*+ch[i]-'';
}
return s;
}
int main()
{
int T,cas=;
scanf("%d",&T);
while(T--)
{
init();
char ch[];
int m ,u,v; //边数
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d%s",&u,ch);
m=cal_num(ch); //截取出数字存入m——边数
for(int j=;j<=m;j++){
scanf("%d",&v);
G[u].push_back(v); //这里按单向边任意一边存储就可以了,毕竟是无向图!
G[v].push_back(u);
}
}
printf("Case %d:\n",++cas);
solve();
}
return ;
}
Light OJ - 1026 - Critical Links(图论-Tarjan算法求无向图的桥数) - 带详细注释的更多相关文章
- tarjan算法求无向图的桥、边双连通分量并缩点
// tarjan算法求无向图的桥.边双连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> ...
- Light OJ 1026 - Critical Links (图论-双向图tarjan求割边,桥)
题目大意:双向联通图, 现在求减少任意一边使图的联通性改变,按照起点从小到大列出所有这样的边 解题思路:双向边模版题 tarjan算法 代码如下: #include<bits/stdc++.h& ...
- [Tarjan系列] Tarjan算法求无向图的桥和割点
RobertTarjan真的是一个传说级的大人物. 他发明的LCT,SplayTree这些数据结构真的给我带来了诸多便利,各种动态图论题都可以用LCT解决. 而且,Tarjan并不只发明了LCT,他对 ...
- [Tarjan系列] Tarjan算法求无向图的双连通分量
这篇介绍如何用Tarjan算法求Double Connected Component,即双连通分量. 双联通分量包括点双连通分量v-DCC和边连通分量e-DCC. 若一张无向连通图不存在割点,则称它为 ...
- tarjan算法--求无向图的割点和桥
一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 2.割点:无向连通图中 ...
- SPF Tarjan算法求无向图割点(关节点)入门题
SPF 题目抽象,给出一个连通图的一些边,求关节点.以及每个关节点分出的连通分量的个数 邻接矩阵只要16ms,而邻接表却要32ms, 花费了大量的时间在加边上. // time 16ms 1 ...
- tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)
基本概念 给定无向连通图G = (V, E)割点:对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点割边(桥)若对于e∈E,从图中删去边e之后,G分 ...
- Tarjan算法求割点
(声明:以下图片来源于网络) Tarjan算法求出割点个数 首先来了解什么是连通图 在图论中,连通图基于连通的概念.在一个无向图 G 中,若从顶点i到顶点j有路径相连(当然从j到i也一定有路径),则称 ...
- Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)
Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...
随机推荐
- HTML:给body增加全屏的背景图
只需要在head中增加如下代码即可 <head> {#设置背景#} <style> body { height: 100%;width: 100%; background: u ...
- WPF 使用winform的webbrowser
首先要添加如下引用: WindowsFormsIntegration System.Drawing System.Windows.Forms 然后在xaml中添加引用 xmlns:winform=&q ...
- [转帖]微软 SQ1 参数一览:8 核 Kryo 495,Adreno 685 GPU
微软 SQ1 参数一览:8 核 Kryo 495,Adreno 685 GPU http://www.myzaker.com/article/5d989ef68e9f0977765e5506/ 微软发 ...
- Quartz.Net—Calendar
动态的排除一些触发器的时间. DailyCalendar-天日历 定义: This implementation of the Calendar excludes (or includes - see ...
- Spring之27:BeanDefinitionRegistry
关于BeanDefinition见<Spring之Ⅰ:BeanDefinition> BeanDefinitionRegistry的类图: BeanDefinition 的注册接口,如 R ...
- eclipse设置text file encoding UTF-8和文件的换行符 Unix 格式
阿里华山版java开发手册代码格式第10条: 步骤:1.Window - Preferences, 2.左边选择 General - Workspace , 3.右边Text file encodin ...
- [C++] 二叉树计算文件单词数
目录 前置技能 构造和遍历二叉树 文件的打开.读取和写入 需求描述 读取文件 构建二叉树 格式化输入输出 具体实现 main.cpp binarytree.h binarytree.cpp 使用二叉树 ...
- Python23之内置函数filter()和map()
首先我们了解一个概念:迭代 迭代是访问集合元素的⼀种⽅式.迭代器是⼀个可以记住遍历的位置的对象.迭代器对象从集合的第⼀个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退. 我们已经知道 ...
- Vue自定义指令和自定义过滤器
一.自定义指令: 自定义指令分为两种:全局自定义指令和局部自定义指令 全局指令指所有组件都可以使用,局部指令是只有在当前组件中才可以使用. 如,我们现在有个需求,当一个输入框获取焦点时,显示出一个di ...
- Vue响应式变化
Vue有一个很方便的特性就是Vue的双向绑定,即响应式变化,在Vue2.X版本中,Vue响应式变化靠的是Object.defineProperty方法实现的,但是这个方法有个问题,就是对数组的支持不全 ...