DAG的深度优先搜索标记
这是图论的基础知识点,也是学习Tarjan的导学课。
一、知识
对于在图G上进行深度优先搜索算法所产生的深度优先森林Gt,我们可以定义四种边的类型:
1.树边(Tree Edge):为深度优先森林中Gt的边。如果结点v是因算法对边(u,v)的搜索而首先被发现,则(u,v)是一条树边。
2.后向边(Back Edge):后向边(u,v)是将结点u连接到其在深度优先树中(一个)祖先结点v的边,由于有向图中可以有自循环,自循环也被认为是后向边。
3.前向边(Forward Edge):是将结点u连接到其在深度优先树中一个后代结点v的边(u,v)。
4.横向边(Cross Edge):指其他所有的边。这些边可以连接同一棵深度优先树中的结点,只要其中一个结点不是另外一个结点的祖先,也可以连接不同深度优先树中的两个结点。
附图:
二、方法
我们采取时间戳的思想:不会戳这里。
1.我们根据深度优先搜索的基本操作需要一个记录顶点相连的标志,也就是edge[][]的一个二维数组, 然后,在遍历各个顶点的过程中将遇到的可以访问的edge设置为-1(初始化为0,输入时置为1)也就是已经访问过了, 至此,我们的树就会生成,但是我们需要记录其中不同边的特性,所以,我们增加两个标志位pre,post来记录开始和结束的时间点, 这个时间点起始点为0. 每当进行一次遍历则会将对应的时间点记录到相应顶点的pre和post中去,因此,我们可以有这样的想法: 1、需要判断一条边为back edge的话,只需要查看其相连顶点的post是否存在就可以了,因为从上到下的搜索过程中,只有该顶点结束搜索才会设置相应的结束时间 因而如果当前顶点的遍历都没有结束那么说明与该点相连的顶点形成的边是一条bakc edge。
2.从刚刚到back edge判断中我们可以联想发现,如果当前的顶点需要遍历且相连顶点的pre(开始时间)比当前顶点的pre高,说明这条边跳过一些时间点直接到此点 而且还是从较早到时间点跳转到较晚的时间点,因此这样的一条边是一条down edge。 3、可想而知如果一个顶点遍历的开始时间点远远大于另外一个顶点点话,这样形成的一条边自然就是cross edge了。
#include<iostream>
#include<queue>
#include<algorithm>
#include<set>
#include<cmath>
#include<vector>
#include<map>
#include<stack>
#include<bitset>
#include<cstdio>
#include<cstring>
//---------------------------------Sexy operation--------------------------//
#define cini(n) scanf("%d",&n)
#define cinl(n) scanf("%lld",&n)
#define cinc(n) scanf("%c",&n)
#define cins(s) scanf("%s",s)
#define coui(n) printf("%d",n)
#define couc(n) printf("%c",n)
#define coul(n) printf("%lld",n)
#define debug(n) printf("%d_________________________________\n",n);
#define speed ios_base::sync_with_stdio(0)
#define file freopen("input.txt","r",stdin);freopen("output.txt","w",stdout)
//-------------------------------Actual option------------------------------//
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define Swap(a,b) a^=b^=a^=b
#define Max(a,b) (a>b?a:b)
#define Min(a,b) a<b?a:b
#define mem(n,x) memset(n,x,sizeof(n))
#define mp(a,b) make_pair(a,b)
#define pb(n) push_back(n)
#define dis(a,b,c,d) ((double)sqrt((a-c)*(a-c)+(b-d)*(b-d)))
//--------------------------------constant----------------------------------//
#define INF 0x3f3f3f3f
#define esp 1e-9
#define PI acos(-1)
using namespace std;
#define maxn 1020
#define INF 0x3f3f3f3f
using namespace std;
int pre[101],post[101],edge[101][101],parent[101];
int tag;
void dfs_tag(int cur,int n){
pre[cur]=++tag;
for(int i=0;i<n;i++){
if(edge[cur][i]==1){
if(pre[i]==0){
parent[i]=cur;
edge[cur][i]=-1;
dfs_tag(i,n);
}else{
if(post[i]==0){edge[cur][i]=-2;}
else if(pre[i]>pre[cur]){
edge[cur][i]=-3;
}else{
edge[cur][i]=-4;
}
}
}
}
post[cur]=++tag;
}
void dfs(int n){
memset(pre,0,sizeof(pre));
memset(post,0,sizeof(post));
memset(parent,-1,sizeof(parent));
for (int i = 0; i < n; ++i)
{
if(parent[i]==-1)
dfs_tag(i,n);
}
}
int main(){
int n,m;
int u,v;
int cases;
tag=0;
cin>>m>>n;
for (int i = 0; i < m; ++i)
{
cin>>u>>v;
edge[u][v]=1;
}
dfs(n);
cin>>cases;
while(cases--){
cin>>u>>v;
switch(edge[u][v]){
case -1:
printf("edge (%d,%d) is Tree Edge\n",u,v);
break;
case -2:
printf("edge (%d,%d) is Back Edge\n",u,v);
break;
case -3:
printf("edge (%d,%d) is Down Edge\n",u,v);
break;
case -4:
printf("edge (%d,%d) is Cross Edge\n",u,v);
break;
}
}
}
DAG的深度优先搜索标记的更多相关文章
- 用深度优先搜索(DFS)解决多数图论问题
前言 本文大概是作者对图论大部分内容的分析和总结吧,\(\text{OI}\)和语文能力有限,且部分说明和推导可能有错误和不足,希望能指出. 创作本文是为了提供彼此学习交流的机会,也算是作者在忙碌的中 ...
- 初涉深度优先搜索--Java学习笔记(二)
版权声明: 本文由Faye_Zuo发布于http://www.cnblogs.com/zuofeiyi/, 本文可以被全部的转载或者部分使用,但请注明出处. 上周学习了数组和链表,有点基础了解以后,这 ...
- 深度优先搜索(DFS)
定义: (维基百科:https://en.wikipedia.org/wiki/Depth-first_search) 深度优先搜索算法(Depth-First-Search),是搜索算法的一种.是沿 ...
- 图的遍历之深度优先搜索(DFS)
深度优先搜索(depth-first search)是对先序遍历(preorder traversal)的推广.”深度优先搜索“,顾名思义就是尽可能深的搜索一个图.想象你是身处一个迷宫的入口,迷宫中的 ...
- AOJ 0118 深度优先搜索
日文题... 题意:一个面积为H*W的果园,种了苹果,梨和蜜柑.相邻(上下左右)的果树属于同一个区域,问果园共有多少个区域. 分析:迷宫问题.对于每一个格子,可以用深度优先搜索把相同果树的格子遍历并标 ...
- 广度优先(bfs)和深度优先搜索(dfs)的应用实例
广度优先搜索应用举例:计算网络跳数 图结构在解决许多网络相关的问题时直到了重要的作用. 比如,用来确定在互联网中从一个结点到另一个结点(一个网络到其他网络的网关)的最佳路径.一种建模方法是采用无向图, ...
- 【算法导论】图的深度优先搜索遍历(DFS)
关于图的存储在上一篇文章中已经讲述,在这里不在赘述.下面我们介绍图的深度优先搜索遍历(DFS). 深度优先搜索遍历实在访问了顶点vi后,访问vi的一个邻接点vj:访问vj之后,又访问vj的一个邻接点, ...
- "《算法导论》之‘图’":深度优先搜索、宽度优先搜索(无向图、有向图)
本文兼参考自<算法导论>及<算法>. 以前一直不能够理解深度优先搜索和广度优先搜索,总是很怕去碰它们,但经过阅读上边提到的两本书,豁然开朗,马上就能理解得更进一步. 下文将会用 ...
- 深度优先搜索(DFS)与广度优先搜索(BFS)的Java实现
1.基础部分 在图中实现最基本的操作之一就是搜索从一个指定顶点可以到达哪些顶点,比如从武汉出发的高铁可以到达哪些城市,一些城市可以直达,一些城市不能直达.现在有一份全国高铁模拟图,要从某个城市(顶点) ...
随机推荐
- 家庭记账本app进度之关于tap的相关操作1
今天还主要学习关于怎样制作微信的先关的tap. 今天的主要成果是已经了解了相关的技术,以及相关的思路.代码经过一个下午的编写,基本接近尾声. 更详细的实验代码,以及相关的知识点将在明天完善后进行发表. ...
- scrapy中使用selenium来爬取页面
scrapy中使用selenium来爬取页面 from selenium import webdriver from scrapy.http.response.html import HtmlResp ...
- Java第十二天,权限修饰符
Java当中权限修饰符共有四种.分别是public.protected.(default).private. 注:YSE代表可访问,NO代表不可访问. 同一个类 同一个包,非继承 不同的包,有继承 ...
- DataAnalysis-Pandas分组聚合
title: Pandas分组聚合 tags: 数据分析 python categories: DataAnalysis toc: true date: 2020-02-10 16:28:49 Des ...
- [编译] 7、在Linux下搭建安卓APP的开发烧写环境(makefile版-gradle版)—— 在Linux上用命令行+VIM开发安卓APP
April 18, 2020 6:54 AM - BEAUTIFULZZZZ 目录 0 前言 1 gradle 安装配置 1.1 卸载系统默认装的gradle 1.2 下载对应版本的二进制文件 1.3 ...
- 计时线程Runnable和Handler的结合
利用Runnable和Handler,来创建计时线程 private double recodeTime = 0;// 用于计时 private double econdTime = 0;// 用于计 ...
- SpeedButton
SpeedButton是一个图形控件,本身没有句柄.因此它不能具有焦点.你可以使用TBitBtn,调整一些属性,可以使他们的外形很接近. 只有从TWinControl派生的控件,才具有Handle.你 ...
- 10个步骤教你如何安装Anaconda安装,Python数据分析入门必看
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:小白 PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行 ...
- F - Select Half dp
题目大意:从n个数里边选n/2个数,问和最大是多少. 题解:这是一个比较有意思的DP,定义状态dp[i][1],表示选了第i个数的最优状态,dp[i][0]表示没有选第i个数的最优状态. 状态是如何转 ...
- java文件上传、下载、图片预览
多文件保存到本地: @ResponseBody @RequestMapping(value = "/uploadApp",produces = { "applica ...