拓扑排序(基于dfs+基于队列)
经典问题-Ordering Tasks
dfs函数的返回值表示是否成环,若存在有向环,则不存在拓扑排序。不包含有向环的有向图称为有向无环图(DAG)
可以借助DFS完成拓扑排序,在访问完一个结点时把他加入当前拓扑序的首部。
举个栗子:比如一个(1,2),(1,3),(2,3)的有向无环图,就先搜索1,再递归搜索2,再搜索3,3没有出度了,于是放进拓扑序尾=,再回到2,2除3外没有出度,再放入拓扑序,再回到1,1除2,3没有出度,放入拓扑序
1 #include <algorithm> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <iostream> 6 #include <cstdlib> 7 #include <set> 8 #include <vector> 9 #include <cctype> 10 #include <iomanip> 11 #include <sstream> 12 #include <climits> 13 #include <queue> 14 #include <stack> 15 using namespace std; 16 typedef long long ll; 17 #define INF 0X3f3f3f3f 18 const ll MAXN = 1e3 + 7; 19 const ll MOD = 1e9 + 7; 20 int mp[MAXN][MAXN]; 21 int vis[MAXN]; 22 int topo[MAXN], t;//topo数组存放最后拓扑排序结果 23 int n,k,m; 24 bool dfs(int u)//判环 25 { 26 vis[u] = -1; //访问标志 27 for(int i=1;i<=n;i++) 28 { 29 if(mp[u][i]) 30 { 31 if(vis[i]==-1) return false;//存在有向环,退出 32 if(!vis[i]&&!dfs(i)) return false; 33 } 34 } 35 topo[--k]=u; 36 vis[u]=1; 37 return true; 38 } 39 bool toposort() 40 { 41 memset(vis,0,sizeof(vis)); 42 k=n; 43 for(int i=1;i<=n;i++) 44 if(!vis[i]&&!dfs(i)) return false; 45 return true; 46 } 47 void print() 48 { 49 for(int i=0;i<n;i++) 50 { 51 if(i) cout<<' '; 52 cout<<topo[i]; 53 } 54 cout<<endl; 55 return ; 56 } 57 int main() 58 { 59 ios::sync_with_stdio(false); 60 while (cin >> n >> m&&(n|m)) 61 { 62 memset(mp,0,sizeof(mp)); 63 for (int i = 0; i < m; i++) 64 { 65 int a,b; 66 cin>>a>>b; 67 mp[a][b]=1; 68 } 69 if(toposort()) 70 print(); 71 else 72 cout<<"sorry to say there is no DAG"<<endl;//跟题目并没有关系... 73 } 74 return 0; 75 }
加个队列写法..
1 #include <algorithm> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <iostream> 6 #include <cstdlib> 7 #include <set> 8 #include <vector> 9 #include <cctype> 10 #include <iomanip> 11 #include <sstream> 12 #include <climits> 13 #include <queue> 14 #include <stack> 15 using namespace std; 16 typedef long long ll; 17 #define INF 0X3f3f3f3f 18 const ll MAXN = 1e3 + 7; 19 const ll MOD = 1e9 + 7; 20 int n, m; 21 int degree[MAXN][MAXN]; 22 int indegree[MAXN]; 23 int topo[MAXN]; 24 void toposort() 25 { 26 int cnt = 0; 27 queue<int> que; 28 for (int i = 1; i <= n; i++) 29 if (!indegree[i]) 30 que.push(i); 31 int cur; 32 while (!que.empty()) 33 { 34 cur = que.front(); 35 que.pop(); 36 topo[cnt++] = cur; 37 for (int i = 1; i <= n; i++) 38 { 39 if (degree[cur][i]) 40 { 41 indegree[i]--; 42 if (!indegree[i]) 43 que.push(i); 44 } 45 } 46 } 47 return; 48 } 49 void print() 50 { 51 for (int i = 0; i < n; i++) 52 { 53 if (i) 54 cout << ' '; 55 cout << topo[i]; 56 } 57 cout << endl; 58 return; 59 } 60 int main() 61 { 62 ios::sync_with_stdio(false); 63 while (cin >> n >> m && (n | m)) 64 { 65 memset(degree, 0, sizeof(degree)); 66 memset(indegree, 0, sizeof(indegree)); 67 while (m--) 68 { 69 int a, b; 70 cin >> a >> b; 71 if (!degree[a][b]) 72 { 73 degree[a][b] = 1; 74 indegree[b]++; 75 }//处理重边 76 } 77 toposort(); 78 print(); 79 } 80 return 0; 81 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
· 程序员常用高效实用工具推荐,办公效率提升利器!