赞
踩
拓扑排序是对有向无圈图的顶点的一种排序,使得如果存在一条从vi到vj的路径,那么在排序中,vi必须出现在vj的前面。
首先,我们需要准备一个vector<int> link[maxn]
,link[i] 存放顶点i
所有连接到的顶点,同时还要维护一个队列或者栈来存放所有入度为0的顶点。
下面,直接上图:
假如有这样一个有向图:
res=[1]
res=[1,2]
3. 目前顶点5的入度为0,把顶点5给去掉。res=[1,2,5]
4. 目前顶点4的入度为0,把顶点4给去掉。res=[1,2,5,4]
5. 目前顶点3的入度为0,把顶点3给去掉。res=[1,2,5,4,3]
直到最后不剩下顶点时,排序结束,1 2 5 4 3
即为该图的一个拓扑排序。
细节:
1 5 4 3 2
代码如下:
// Kahn算法 #include <bits/stdc++.h> using namespace std; typedef long long ll; #define maxn 1024 vector<int> link[maxn]; //顶点i的邻接表 queue<int> q; //存放所有入度为0的顶点 int in[maxn]; //顶点i的入度 int n; //顶点个数 int m; //边的个数 int res[maxn]; //存放排序后的结果 /* 新增一条由n1指向n2的有向边 */ void lnk(int n1,int n2){ link[n1].push_back(n2); //n1顶点的邻接表加入n2 ++in[n2]; //n2的入度+1 } int main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); //建图 n = 13; m = 15; lnk(1,2); lnk(1,6); lnk(1,7); lnk(3,1); lnk(3,4); lnk(4,6); lnk(6,5); lnk(7,4); lnk(7,10); lnk(8,7); lnk(9,8); lnk(10,11); lnk(10,12); lnk(10,13); lnk(12,13); //扫描in数组,将入度为0的顶点加入队列 for(int i = 1;i <= n;++i){ if(!in[i]){ q.push(i); } } int index = 0; //res的下标 while(!q.empty()){ int node = q.front(); q.pop(); //拿出一个结点 res[index++] = node; //存入结果数组 //逐一移除跟它相连的边 for(auto it = link[node].begin();it != link[node].end();++it){ --in[*it]; //顶点入度-1 if(!in[*it]){ //如果入度为0,加入队列 q.push(*it); } } } //如果index<n,那么加入结果数组的顶点数量一定是小于n的 //说明该图有环 if(index == n){ for(int i = 0;i<n;++i){ cout << res[i] << " \n"[i == n-1]; } }else{ cout << "circulation" << endl; } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。