hiho 第215周 Circle Detect(拓扑排序 | DFS)
Posted ehanla
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hiho 第215周 Circle Detect(拓扑排序 | DFS)相关的知识,希望对你有一定的参考价值。
1.对于判断有向图是否有环
拓扑排序:
拓扑排序原理:
1. 从DAG(有向无环图)中选一个 没有前驱(即入度为0)的顶点并输出。
2. 从图中删除该顶点和所有以它为起点的有向边。
3. 重复1和2直到当前的DAG为空或当前图中不存在无前驱的顶点为止,后一种情况说明有向图中一定有环。
时间复杂度:O(n+e),顶点个数和边的条数。
1 //拓扑排序 判断有向图是否有环 2 #include <queue> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 8 const int N=1e5+10; 9 int in[N]; 10 queue <int> Q; 11 int t,n,m,cnt; 12 vector <int> E[N]; 13 14 void toposort(){ 15 for(int i=1;i<=n;i++){ 16 if(in[i]==0) Q.push(i); 17 } 18 while(!Q.empty()){ 19 cnt++; 20 int u=Q.front(); 21 Q.pop(); 22 for(int i=0;i<E[u].size();i++){ 23 int v=E[u][i]; 24 in[v]--; 25 if(in[v]==0) Q.push(v); 26 } 27 } 28 } 29 30 int main(){ 31 scanf("%d",&t); 32 while(t--){ 33 cnt=0; 34 memset(in,0,sizeof(in)); 35 for(int i=1;i<N;i++) E[i].clear(); 36 scanf("%d%d",&n,&m); 37 for(int i=1;i<=m;i++){ 38 int x,y; 39 scanf("%d%d",&x,&y); 40 E[x].push_back(y); 41 in[y]++; 42 } 43 toposort(); 44 if(cnt==n) printf("NO "); 45 else printf("YES "); 46 } 47 return 0; 48 }
DFS:
DFS过程中对点染色:
- 还没被DFS访问的点是白色的,初始时所有点都是白色的
- 如果点u已经被DFS访问过,但是u的子节点还未全部被访问到,那么把u染成灰色
- 如果点u以及u的子节点都被访问过了,从u回溯到u的父节点时,将u染成黑色
如果在DFS的过程中我们沿着有向边到达了一个灰色节点,则说明图中有环;如果从未到达过灰色节点,说明没有环。
时间复杂度:O(n+e),顶点个数和边的条数。
1 //DFS 判断有向图是否有环 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 using namespace std; 8 9 const int N=1e5+10; 10 vector <int> E[N]; 11 int f,vis[N]; 12 13 void dfs(int u){ 14 if(f) return ; 15 vis[u]=-1; 16 for(int i=0;i<E[u].size();i++){ 17 int v=E[u][i]; 18 if(vis[v]==0) dfs(v); 19 else if(vis[v]==-1) {f=1;return ;} 20 } 21 vis[u]=1; 22 } 23 24 int main(){ 25 int t,n,m; 26 scanf("%d",&t); 27 while(t--){ 28 f=0; 29 memset(vis,0,sizeof(vis)); 30 for(int i=1;i<N;i++){ 31 E[i].clear(); 32 } 33 scanf("%d%d",&n,&m); 34 int a,b; 35 for(int i=1;i<=m;i++){ 36 scanf("%d%d",&a,&b); 37 E[a].push_back(b); 38 } 39 for(int i=1;i<=n;i++){ 40 if(f) break; 41 if(vis[i]==0) dfs(i); 42 } 43 if(f==1) printf("YES "); 44 else printf("NO "); 45 } 46 return 0; 47 }
注意:注意对vector存边的清空。
2.判断无向图是否有环
假设无向图存在n个连通子图。如果无向图无环,说明每个连通子图都是棵树,即该连通子图的顶点数(vi)=边数(ei)+1。
最后得到:V=E+n
以上是关于hiho 第215周 Circle Detect(拓扑排序 | DFS)的主要内容,如果未能解决你的问题,请参考以下文章