[容易] DAG的拓扑排序
来源:互联网 发布:修改数据库system密码 编辑:程序博客网 时间:2024/05/17 04:13
DAG的拓扑排序可以采用两种方法来求解:入度法和DFS
DFS比较好写,而且不需要掌握额外的算法,不过处理起实际问题来,DFS法不如入度法方便,因此在这里我推荐大家采用入度法来求拓扑排序。
这里先给出一个入度法的例子,后面会给出一个DFS的例子。
- 题目描述:
有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。
- 输入:
输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。
- 输出:
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
- 样例输入:
4 31 22 34 3
- 样例输出:
1 2 4 3
本题只是一个简单的拓扑排序,不过要注意的一点是它要求当符合条件的排名不唯一时,输出时编号小的队伍在前,因此下面的代码中使用了优先队列来处理这一点。
#include <iostream>#include <vector>#include <queue>using namespace std;const int maxn=500+5;struct Edge{ int from,to; Edge(int tf,int tt):from(tf),to(tt){}};vector<Edge> edges;vector<int> G[maxn];int topo[maxn];int inDegree[maxn];int main(){ int n,m; while(cin>>n>>m) { fill(inDegree,inDegree+n+1,0); for(int i=1;i<=n;++i) G[i].clear(); for(int i=0;i<m;++i) { int a,b; cin>>a>>b; edges.push_back(Edge(a,b)); G[a].push_back(edges.size()-1); ++inDegree[b]; } priority_queue<int,vector<int>,greater<int> > q; while(!q.empty()) q.pop(); for(int i=1;i<=n;++i) { if(inDegree[i]==0) q.push(i); } int cnt=0; while(!q.empty()) { int t=q.top(); topo[++cnt]=t; q.pop(); for(int i=0;i<G[t].size();++i) { Edge& e=edges[G[t][i]]; --inDegree[e.to]; if(inDegree[e.to]==0) q.push(e.to); } } if(cnt==n) { bool first=true; for(int i=1;i<=n;++i) { if(first) first=false; else cout<<" "; cout<<topo[i]; } cout<<endl; } } return 0;}[注意]
通过判断cnt是否等于n,可以判断该图是不是DAG,也就是有没有环。当cnt等于n时是DAG,无环。
下面顺便给出一个DFS求拓扑排序的例子,其实DFS主要可以用来判环,顺带可以求出拓扑序。
题目描述
本题只需要使用DFS来判断是否有环即可,判断的同时可以求出拓扑序。
具体代码:
#include <iostream>using namespace std;const int maxn=100+5;int c[maxn];int topo[maxn];bool G[maxn][maxn];int n,m;int t;bool dfs(int u){ c[u]=-1;//now u is being searched for(int i=0;i<n;++i) { if(G[u][i]) { if(c[i]==-1||(!c[i]&&!dfs(i))) return false;//There is a circle. Not DAG. } } c[u]=1; topo[--t]=u;//注意DFS求的是拓扑逆序 return true;}int main(){ for(cin>>n>>m;n!=0;cin>>n>>m) { t=n; for(int i=0;i<n;++i) fill(G[i],G[i]+n,false); fill(c,c+n,0); for(int i=0;i<m;++i) { int a,b; cin>>a>>b; G[a][b]=true; } bool DAG=true; for(int i=0;i<n;++i) { if((!c[i])&&(!dfs(i))) { DAG=false; break; } } /*if(DAG) { for(int i=0;i<n;++i) cout<<topo[i]<<" "; cout<<endl; } else cout<<"Not DAG\n";*/ cout<<(DAG?"YES":"NO")<<endl; } return 0;}
如果采用DFS方法来求解上一题,可能就不是那么方便了,当然如果大家有什么好的方法,欢迎评论交流~
阅读全文
0 0
- [容易] DAG的拓扑排序
- DAG图的拓扑排序 python
- DAG图与拓扑排序
- LightOJ1003-Drunk-拓扑排序,DAG
- 有向无环图(DAG)拓扑排序的两种方法
- 拓扑排序+有向无环图(DAG)的检测
- 算法: 有向无环图(DAG)的拓扑排序
- 数据结构(19)--DAG应用之AOE网的拓扑排序
- poj 2367 Genealogical tree(DAG的拓扑排序)
- hdu 3342 Legal or Not(DAG的拓扑排序)
- 有向无环图(DAG)拓扑排序的两种方法
- 九度:1449<拓扑排序><DAG>
- 【BZOJ4562】[Haoi2016]食物链【DP】【DAG】【拓扑排序】
- Python DAG—归简法—拓扑排序
- UVA自由组合 DAG+拓扑排序
- 用拓扑排序+动态规划的方法输出DAG的所有可能的路径
- 【USACO4.4.3】重叠的图像(DAG图的拓扑排序)
- 应用拓扑排序来解决DAG(directed acylic graph)的单源最短路径问题
- 【功能介绍】ITSOM企业级应用SaaS平台——知识库
- 技巧:知晓当前到底是在哪个活动
- JavaScript返回上一页代码区别:
- MUI显示原生等待框
- HDU 6181 Two Paths (次短路)
- [容易] DAG的拓扑排序
- 范式
- 如何在服务器上搭建一个lamp(Linux(CentOS7)+Apache+MySQL+PHP)环境
- ApplicationInfo 存储信息放上来是方便查看
- LAMP之apache源码安装
- java Arrays.asList com.google.common.collect.Lists.newArrayList 效率问题
- HTTP协议中PUT和POST使用区别
- js 合并json数组中有同一key值的json
- 学习Opencv 2.4.9(二) ---操作像素