SeekLuna P1362 拓扑排序 3 题解
拓扑排序 3
题意
有一个由
请求出所有
按照字典序从小到大输出。
数据范围
- 保证图无环且无重边,保证答案不超过
种
思路
首先排除普通的全排列搜索,时间复杂度爆炸了。(高级全排列搜索)
分析一下题意,其实就是这个点在加入答案序列时,所有可以连向它的点都必须已经加入到了答案序列中。
这样一看,很明显是有一个拓扑序在的。那么我们就可以考虑使用拓扑排序。
由于这道题要求出所有满足要求的全排列,那么我们就不能用 while
循环版本的拓扑排序,要用类 dfs
的拓扑排序来做,每次dfs时枚举一下选择哪个合法的点加入答案序列中,最后输出即可。
即dfs操作大致为:
- 枚举所有入度为
的点,将其加入答案序列中。 - 将所有从这个点连出去的边删除,同时记录一下又有哪些点的入度变为了
,将其加入入度为 的点的序列当中- 其实这里并不是真正的删除(至少我的做法不是),只是将那些点的入度暂时减少
,当下一层搜索彻底结束时,需要将这些点入度重新加 ,即回溯 - 这里为了保证字典序,进行下一层搜索之前需要排序一下。
- 其实这里并不是真正的删除(至少我的做法不是),只是将那些点的入度暂时减少
- 进行下一层的搜索
复杂度
- 时间:
- 每次搜索
,题目保证答案数量不超过
- 每次搜索
- 空间:
- 记录答案等
,vector
存储邻接表
- 记录答案等
Code
点击查看代码
有点丑啊……
#include <iostream> #include <queue> #include <algorithm> #include <vector> using namespace std; const int N = 30; int n, m, stk[N], top, x, y, f[N], no, b[N], ans[N]; vector<int> a[N]; void dfs (int stk[], int top, int no) { if (!no) { // 一种情况的结束 for (int i = 0; i < n; i++) { // 输出答案 cout << ans[i] << ' '; } cout << '\n'; return ; } int t; for (int j = 0; j < top; j++) { ans[n - no] = stk[j]; // stk 中存储了所有的入度为 0 的点 t = stk[j]; // 记录当前选择的点 f[t] = 1; int stk_[N], top_ = 0; // 记录所有入度为 0 的点,记得把 stk 中的其他点算进去 for (int i = 0; i < top; i++) { if (i != j) { stk_[top_++] = stk[i]; } } for (int i = 0; i < a[t].size(); i++) { if (!f[a[t][i]]) { b[a[t][i]]--; // 入度减 1 if (!b[a[t][i]]) { // 产生了入度为 0 的点 stk_[top_++] = a[t][i]; // 压入 stk_ } } } sort(stk_, stk_ + top_); // 记得要排序 dfs(stk_, top_, no - 1); // 下一层搜索 // 下面这一段是回溯 for (int i = 0; i < a[t].size(); i++) { if (!f[a[t][i]]) { b[a[t][i]]++; } } f[t] = 0; } } int main(){ ios::sync_with_stdio(0), cin.tie(0); cin >> n >> m; no = n; for (int i = 1; i <= m; i++) { cin >> x >> y; a[x].push_back(y); // vector 存储邻接矩阵 b[y]++; // 入度的统计 } for (int i = 1; i <= n; i++) { if (!b[i]) { // 第一轮的入度为 0 的点 stk[top++] = i; } } dfs(stk, top, no); // 调用 dfs return 0; }
本文作者:wnsyou の blog
本文链接:https://www.cnblogs.com/wnsyou-blog/p/17211581.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步