1.用途:可以判断有向图(➀可以存在孤立结点➁也可以有重边)是否存在环。
2.代码模板:
1)顶点少于1000的图可以用邻接矩阵来存储:
➀用STL中的栈略耗时,但代码量略少
#include<iostream> #include<cstdio> #include<cstring> #include<stack> #define Max(a,b) ((a)>(b)?(a):(b)) #define N 1005 using namespace std; int mat[N][N]; int in[N]; int n,m; void Topo() { int i,j; stack<int> S; for(i=0;i<n;i++) { if(in[i]==0) { S.push(i); in[i]=-1; } } int cnt=0; while(!S.empty()) { i=S.top(); S.pop(); cnt++; for(j=0;j<n;j++) { in[j]-=mat[i][j]; if(in[j]==0) { S.push(j); in[j]=-1; } } } if(cnt==n) printf("YES\n"); else printf("NO\n"); } int main() { int i; while(scanf("%d%d",&n,&m)&&(n||m)) { memset(in,0,sizeof(in)); memset(mat,0,sizeof(mat)); for(i=0;i<m;i++) { int a,b; scanf("%d%d",&a,&b); mat[a][b]++; in[b]++; } Topo(); } return 0; }➁用数组模拟的栈略省时
#include<iostream> #include<cstdio> #include<cstring> #define Max(a,b) ((a)>(b)?(a):(b)) #define N 1005 using namespace std; int mat[N][N]; int in[N]; int n,m; int Stack[N],top; void Topo() { int i,j; top=0; for(i=0;i<n;i++) { if(in[i]==0) { Stack[++top]=i; in[i]=-1; } } int cnt=0; while(top!=0) { i=Stack[top--]; cnt++; for(j=0;j<n;j++) { in[j]-=mat[i][j]; if(in[j]==0) { Stack[++top]=j; in[j]=-1; } } } if(cnt==n) printf("YES\n"); else printf("NO\n"); } int main() { int i; while(scanf("%d%d",&n,&m)&&(n||m)) { memset(in,0,sizeof(in)); memset(mat,0,sizeof(mat)); for(i=0;i<m;i++) { int a,b; scanf("%d%d",&a,&b); mat[a][b]++; in[b]++; } Topo(); } return 0; }
2)顶点少于1000的图可以用邻接表来存储:
➀用STL中的vector模拟略耗时,但代码量略少
#include<iostream> #include<cstdio> #include<cstring> #include<stack> #include<vector> using namespace std; vector<int> vec[105]; int n,m; int in[105]; void Topo() { int i,j; stack<int> S; for(i=0;i<n;i++) { if(in[i]==0) { S.push(i); in[i]=-1; } } int cnt=0; while(!S.empty()) { i=S.top(); S.pop(); cnt++; for(j=0;j<vec[i].size();j++) { int k=vec[i][j]; in[k]--;//和邻接矩阵不同 if(in[k]==0) { S.push(k); in[k]=-1; } } } if(cnt==n) printf("YES\n"); else printf("NO\n"); } int main() { int i; while(scanf("%d%d",&n,&m)&&(n||m)) { memset(in,0,sizeof(in)); for(i=0;i<n;i++) { vec[i].clear(); } for(i=0;i<m;i++) { int a,b; scanf("%d%d",&a,&b); in[b]++; vec[a].push_back(b);//重边也包括进去了,形式与邻接矩阵不同 } Topo(); } return 0; }
➁用链表写邻接表代码较多,不适合于比赛和考试,此处就省略了。