首页 > 搜索 > 传递闭包算法的参考文献,算法学习笔记(一):拓扑排序与传递闭包(通过bfs&&dfs)

传递闭包算法的参考文献,算法学习笔记(一):拓扑排序与传递闭包(通过bfs&&dfs)

互联网 2020-10-31 09:02:55
在线算命,八字测算命理
       今天写一下关于拓扑排序与dfs的一点学习经验。

    首先说说拓扑排序吧

    拓扑排序可以用dfs,经典的队列算法(也能用堆栈实现)

    首先说一下什么是拓扑排序,有时候一些任务会产生依赖关系。即做A需要先做B,则A依赖与B

    然后通过拓扑排序,产生一个序列,满足这些先后依赖关系。

    关于拓扑排序的几个算法:

    一  dfs

void dfs(int x){assert(visit[x]==false);visit[x]=true;for(vector::iterator it=G[x].begin() ;it != G[x].end() ; it++ ){if( !visit[*it] ){dfs(*it);}}ans[an++]=x;} void solve(){an=0;for(int i=1;i=0;--i){(i==an-1)?printf("%d",ans[i]):printf(" %d",ans[i]);}putchar('\n');}

即是先通过dfs将一个接点的后续子节点遍历完毕后,再记录自己到一个数组里面。

这样最后导致的是数组需要逆序输出才得到拓扑排序(想一想,为什么)

当然,上面这个程序并没有判环,适合纯粹的DAG。

如果有环,怎么办?

这个时候需要一些技巧,

将一个visit数组这样记录

visit[node]  ==  0  表示尚未被访问

visit[node] == 1   表示正在被访问,但是它的所有子节点尚未被访问完

visit[node] == 2  表示已经被访问,并且它的所有子节点已经被访问完

如果在访问过程中遇见visit[node] == 1  则说明有环

实现很简单,具体留给大家

二  队列实现拓扑排序

这个先要预处理,记录每个节点的入度。

然后,将入度为0的节点入队列

每次从队列弹出节点时,将该接点的相连边全部删除

voiddag(DAGD,int ts[]){int i,v;linkt;for(v=0 ; vV;v++){in[v]=0;ts[v]=-1; } for(v=0; vV;v++){for(t=D->adj[v];t!=NULL;t=t->next){ in[t-v]++;} } Queue Q; for(v=0;vv;v++){if( in[v] == 0 )Q.push(v); } for(i=0;!Q.empty();i++){ v=Q.front(); Q.pop(); ts[i]=v; for( t=D->adj[v]; t!=NULL ; t=t->next ){if(--in[t->v]== 0 )Q.push(t->v);} } }

那么上面怎么判断环呢,很简单,只要判断ts数组里面加入的数是否等于顶点数即可

好了,基本也讲完了。现在我提出两个个思考题,怎样利用拓扑排序求最长路,怎样判断一个DAG是否是哈密顿回路?(与最长路有关)

上面两个思考题基本上是等价的。

三  传递闭包

     

/* 自反传递闭包*/void dfs(int u,int v){newgraph[u][v]=true; //suggest newgrap[u][v] has been added in the newgraghfor( it =G[v].begin() ; it != G[v].end() ; ++it ){// find from the adj edge,"it" is the iteratorif( newgraph[u][*it] == false ){dfs(u,*it);}}}void solve(){memset(newgraph,false,sizeof(newgraph));// the newgraph is the Pass closuresfor(int i=0;i
免责声明:非本网注明原创的信息,皆为程序自动获取互联网,目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责;如此页面有侵犯到您的权益,请给站长发送邮件,并提供相关证明(版权证明、身份证正反面、侵权链接),站长将在收到邮件12小时内删除。

相关阅读

一周热门

查看更多