处理何种问题:虽说是排序,但是主要作用是判断有向图是否有环。
性能:时间复杂度为O(E),E为边的个数。
原理:每次找入度为0的点入栈,然后将与此相连的节点入度减1;重复以上步骤,直到栈中为空。记录弹出节点次数,如果次数与节点总数相同,及无环,否则,有环的存在。(证明的时候注意,如果一个点的入度已变为0,则再也不会有其他点能到达它)
实现步骤:建图(vector)+ 栈(队列) 模拟
备注:略
输入样例解释:
2 2 //n 节点个数,m 边的个数
1 2 //由a 到 b
2 1
3 2
1 2
1 3
输出样例解释:
Cycle //有环
Not Cycle //无环
#include<iostream> #include<cstdio> #include<string.h> #include<algorithm> #include<Stack> #include<vector> using namespace std; const int MaxN=10010; vector<int>edge[MaxN]; stack<int>S; int n,m,ctor; int ind[MaxN];//入度 void init() { ctor=0; memset(ind,0,sizeof(ind)); for(int i=0;i<=n;++i) { edge[i].clear(); } while(!S.empty()) { S.pop(); } } void solve() { for(int i=1;i<=n;++i) //节点必须由1开始 { if(ind[i]==0) S.push(i); } while(!S.empty()) { int temp=S.top(); S.pop(); ++ctor; int len=edge[temp].size(); for(int i=0;i<len;++i) { --ind[edge[temp][i]]; if(ind[edge[temp][i]]==0) S.push(edge[temp][i]); } } } int main() { while(~scanf("%d%d",&n,&m)) { init(); int a,b; while(m--) { scanf("%d%d",&a,&b); ++ind[b]; edge[a].push_back(b); } solve(); if(ctor==n) printf("Not Cycle "); else printf("Cycle "); } return 0; }