这道题要求没有输赢关系的两个元素必须按照升序输出,有输赢关系的,赢得在输的前面,所以用队列或者栈来降低时间复杂度的优化过的拓扑排序会出错。
比如这组输入
5 3
1 2
2 3
4 5
至少我写的两种拓扑排序都wa了。但是不用队列或者栈来优化的话,
1.每次都从头至尾扫描一遍,找到一个没标记过的节点,
2.将它标记
3.然后删除从它出来的每条边。
重复这三个操作,加标记的次序,就是题目要的答案。
下面的代码中用到了队列,但只是用来保存答案而已。并没有用它优化的意思。
#include <iostream> #include <vector> #include <queue> #include <stdio.h> #include <memory.h> #include <stack> using namespace std; int counter[505]; bool vis[505]; queue<int> ans; int N,M; vector<vector<int> > v; bool TopoOrder() { for(int i=0;i<N;i++) { int j=1; while(vis[j]||counter[j]!=0) j++; vis[j]=true; ans.push(j); for(int k=0;k<v[j].size();k++) counter[v[j][k]]--; } return true; } void output() { bool isbegin=true; while(!ans.empty()) { if(isbegin) { isbegin=false; cout<<ans.front(); } else cout<<‘ ‘<<ans.front(); ans.pop(); } cout<<endl; } int main() { int a,b; while(~scanf("%d%d",&N,&M)) { memset(counter,0,sizeof(counter)); memset(vis,false,sizeof(vis)); v.clear(); v.resize(N+1); for(int i=0;i<M;i++) { scanf("%d%d",&a,&b); v[a].push_back(b); counter[b]++; } TopoOrder(); output(); } return 0; }
时间: 2024-10-09 22:33:36