拓扑排序判断有向图是否有回路
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<string> 3 #include<queue> 4 using namespace std; 5 const int max_size = 101; 6 typedef struct arcNode{ 7 int node; 8 arcNode *next; 9 }arcNode; 10 typedef struct headNode{ 11 int node; 12 arcNode *firstArc; 13 }adjList[max_size]; 14 typedef struct cmap{ 15 adjList map; 16 int nodeNum, arcNum; 17 }cmap; 18 int inDegree[max_size]; 19 20 int findNode(cmap c, int id){ 21 for(int i=1;i<=c.nodeNum;i++){ 22 if(c.map[i].node==id){ 23 return i; 24 } 25 } 26 return 0; 27 } 28 void createMap(cmap &c){ 29 //input nodeNum and arcNum 30 cin>>c.nodeNum>>c.arcNum; 31 32 //init headNode 33 for(int i=1;i<=c.nodeNum;i++){ 34 c.map[i].node=i; 35 c.map[i].firstArc=NULL; 36 } 37 38 //add arc 39 int from, to; 40 for(int i=1;i<=c.arcNum;i++){ 41 cin>>from>>to; 42 43 arcNode *arc=new arcNode; 44 arc->node=to; 45 arc->next=c.map[from].firstArc; 46 c.map[from].firstArc=arc; 47 } 48 } 49 void getInDegree(cmap c){ 50 for(int i=1;i<=c.nodeNum;i++){ 51 inDegree[i]=0; 52 } 53 for(int i=1;i<=c.nodeNum;i++){ 54 arcNode *p=c.map[i].firstArc; 55 while(p){ 56 inDegree[p->node]++; 57 p=p->next; 58 } 59 } 60 61 } 62 void topoSort(cmap c){ 63 queue<int> q; 64 for(int i=0;i<max_size;i++) inDegree[i]=0; 65 int count = 0; 66 67 getInDegree(c); 68 for(int i=1;i<=c.nodeNum;i++){ 69 if(inDegree[i]==0) q.push(i); 70 } 71 /* 72 if all nodes' indegree doesn't equal to 0, 73 then this map must be not a DAG. 74 */ 75 while(!q.empty()){ 76 int v=q.front(); 77 q.pop(); 78 ++count; 79 arcNode *p=c.map[v].firstArc; 80 while(p){ 81 if(!(--inDegree[p->node])){ 82 q.push(p->node); 83 } 84 p=p->next; 85 } 86 } 87 /* 88 firstly, select a node whose indegree is zero. 89 secondly, delete the node and clear all the arcs that point at the nodeas end. 90 repete the above two steps util the map is NULL @1 91 or the map isn't null, but the rest of nodes in map has more than 1 indegree. @2 92 for situation @1, the map is a DAG. 93 for situation @2, the map is not a DAG. 94 */ 95 /* 96 事实上,如果一个有向图不是一个DAG,那么图中所有的点我们可以把它们划分为 97 两类:环路点和非环路点。非环路点上有弧连接的两点pa->pb构成一个偏序关系,pa为 98 先决条件,pa可以删除从pa出发的所有弧。删除过程中如果pa指向的pb顶点入度为0 99 ,那么就将该pb顶点加入队列(因为是删除了弧以后入度才为0,所以该顶点并没有之 100 前的队列出现过).然后程序从pb顶点重复上述过程,直至栈空。 101 102 最后,如果该有向图不是DAG,那么环路中的所有点都无法构成偏序关系,所以无法进行 103 删除边的动作,所以该图最后剩下一个连通分量。 104 反之,如果该无向图是DAG,图中所有点对只好构成一组偏序关系,则都可进行删除边动作, 105 所以图最后被清空。 106 */ 107 if(count<c.nodeNum){ 108 cout<<"该有向图有回路"<<endl; 109 } 110 } 111 int main(){ 112 113 cmap c; 114 createMap(c); 115 topoSort(c); 116 cout<<endl; 117 }