DAG 的深度优先搜索标记

DAG 的深度优先搜索标记 (参考的一个acm模板,不知道挂啥链接)

邻接矩阵版
/*==================================================*\
 | DAG 的深度优先搜索标记
 | INIT: edge[][]邻接矩阵; pre[], post[], tag全置0;
 | CALL: dfstag(i, n); pre/post:开始/结束时间
\*==================================================*/

/*
注意:发起点——>接受点,中间->即为边,种类如下:
树边(Tree Edge):从一个顶点指向其未访问过的子节点的边。
前向边(Forward Edge):从一个顶点指向该顶点的一个非子顶点后裔的边,且  接受点  被访问过。
回边(Back Edge):从一个顶点指向其祖先顶点的边。
横跨边(Cross Edge):从一个顶点指向一个已完全访问过的顶点,且其中 接受点 既不是  发起点  的的后裔,也不是其祖先。
*/

int edge[V][V], pre[V], post[V], tag;  		//置零

void dfstag(int cur, int n){ 
	// vertex: 0 ~ n-1
 	pre[cur] = ++tag; 			// 开始访问cur
	for(int i = 0; i < n; ++i)		//依次访问cur的 ‘子孙’ 结点
		if(edge[cur][i]){  
 			if(pre[i] == 0){ 		// i 未被访问
			cout << "edge" << cur << -> << i << "is Tree Edge" << endl;
			dfstag(i, n); 
			}
			else{
				if(post[i] == 0) 		// i 子孙后代未被访问完
					cout << "edge" << cur << -> << i << "is Back Edge" << endl;
 				else if (pre[i] > pre[cur]) 		//i 在 cur之后访问
					cout << "edge" << cur << -> << i << "is Down Edge" << endl;
 				else cout << "edge" << cur << -> << i << "is Cross Edge" << endl;		//指向一个完全访问了的结点
			} 
	} 
 	post[cur] = ++tag; 		// cur访问结束
}
/*
DFS过程中,对于一条边cur->i:
pre[i] = 0:说明i还没被访问,i是首次被发现,cur->i是一条  树边  ,真正的dfs路径中的边。
pre[i]!= 0:
	pos[i] = 0:说明i已经被访问,但其子孙后代还没有被访问完, 此时正在结束cur的所有孩子的访问,处于i的递归层次中,而cur又指向i,说明cur就是i的子孙后代,cur->i是一条  后向边  ,因此后向边又称返祖边,有环的时候回去的边,因此判断有没有环可以判断有没有后向边就可以了。
	pos[i] != 0:
    	pre[i] > pre[cur]:说明i已经被访问,其子孙后代也已经全部访问完,cur->i是一条  前向边  ,前向边可以理解为就是父亲指向孩子,但是已经访问过了(非直接孩子)。
	树边,后向边,前向边,都有祖先,后裔的关系,但横跨边没有,cur->i为横跨边,说明在这棵DFS树中,它们不是祖先后裔的关系它们可能是兄弟关系,堂兄弟关系,甚至更远的关系,如果是dfs森林的话,cur和i甚至可以在不同的树上。
*/
邻接表版
int pre[V], post[V], tag;  		//置零
vector<vector<int> > adj; 
void dfstag(int cur, int n){ 
	// vertex: 0 ~ n-1
 	pre[cur] = ++tag; 			// 开始访问cur
	for(int i = 0; i < adj[cur].size(); ++i){		//依次访问cur的 ‘子孙’ 结点  
		int child = adj[cur][i];
 		if(pre[child] == 0){ 		// child 未被访问
			cout << "edge" << cur << -> << child << "is Tree Edge" << endl;
			dfstag(child, n); 
		}
		else{
			if(post[child] == 0) 		// child 子孙后代未被访问完
				cout << "edge" << cur << -> << child << "is Back Edge" << endl;
 			else if (pre[child] > pre[cur]) 		//child 在 cur之后访问
				cout << "edge" << cur << -> << child << "is Down Edge" << endl;
 			else cout << "edge" << cur << -> << child << "is Cross Edge" << endl;		//指向一个完全访问了的结点
		} 
	} 
 	post[cur] = ++tag; 		// cur访问结束
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值