拓扑的实现并不难,无论是dfs还是队列实现代码都相对较短,但应用却并不容易
拓扑应用①排序
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=505; int deg[maxn]; vector<int>g[maxn]; queue<int>q; int n,m,cnt,ans[maxn]; void add_edge(int u,int v) { g[u].push_back(v); } void topo() { while(!q.empty()) q.pop(); for(int i=1;i<=n;i++) if(!deg[i]) {q.push(i);deg[i]--;break;} while(!q.empty()) { int u=q.front();q.pop(); ans[cnt++]=u; for(auto v:g[u]) { deg[v]--; } for(int i=1;i<=n;i++) if(!deg[i]) { q.push(i); deg[i]--; break; } } for(int i=0;i<cnt;i++) { cout<<ans[i]; if(i==cnt-1) cout<<endl; else cout<<" "; } } int main() { ios::sync_with_stdio(false); while(cin>>n>>m){ memset(deg,0,sizeof(deg)); for(int i=0;i<=n;i++) g[i].clear(); cnt=0; for(int i=0;i<m;i++) { int a,b; cin>>a>>b; add_edge(a,b); deg[b]++; } topo(); } return 0; }
拓扑应用②三种状态(有环,顺序不定,顺序确定)的判别
因为题目中有排名相同的情况,这里就要考虑用并查集,将相同的归到一类
判环的时候用到的是sum来标记判断的
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e4+5; const int maxm=2e4+5; int deg[maxn]; int par[maxn]; bool vis[maxn]; vector<int>g[maxm]; queue<int>q; int n,m,flag1=0,sum; void add_edge(int u,int v) { g[u].push_back(v); deg[v]++; } int findx(int x) { if(par[x]!=x) par[x]=findx(par[x]); return par[x]; } bool unionn(int x,int y) { x=findx(x); y=findx(y); if(x==y) return false; else{ par[y]=x; return true; } } /*int dfs(int u)//判环 { vis[u]=-1; for(auto v:g[u]) { if(vis[v]==-1) return 0; else if(vis[v]==0) dfs(v); } vis[u]=1; return 1; }*/ void topo() { while(!q.empty()) q.pop(); for(int i=0;i<n;i++) if(!deg[i]&&par[i]==i) {q.push(i);} while(!q.empty()) { if(q.size()>1) flag1=1; int u=q.front();q.pop();sum--; for(auto v:g[u]) { deg[v]--; if(!deg[v]) q.push(v); } } if(sum>0) cout<<"CONFLICT"<<endl; else if(flag1) cout<<"UNCERTAIN"<<endl; else cout<<"OK"<<endl; } int main() { ios::sync_with_stdio(false); while(cin>>n>>m){ memset(deg,0,sizeof(deg)); //memset(vis,0,sizeof(vis)); for(int i=0;i<n;i++) par[i]=i; for(int i=0;i<=n;i++) g[i].clear(); flag1=0;sum=n; for(int i=0;i<m;i++) { int a,b; char c; cin>>a>>c>>b; if(c==‘=‘) {unionn(a,b);} int x=findx(a); int y=findx(b); if(c==‘<‘) swap(a,b); add_edge(a,b); } /*for(int i=0;i<n;i++) { if(!vis[i]) { if(!dfs(i)) flag2=1; } }*/ topo(); } return 0; }