拓扑的实现并不难,无论是dfs还是队列实现代码都相对较短,但应用却并不容易
HDU - 1285 确定比赛名次 HRBUST - 1631
拓扑应用①排序
#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; }
Codefoeces 510C 哎,,,不太会用dfs版的拓扑,还需要练习
#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
int ans[30];
int vis[30];
int g[30][30],t;
string s[maxn+5];
void init()
{
memset(vis,0,sizeof(vis));
memset(g,0,sizeof(g));
t=26;
}
bool dfs(int u)
{
vis[u]=-1;
for(int i=0;i<26;i++)
if(g[u][i])
{
if(vis[i]==-1) return false;
else if(!vis[i]&&!dfs(i)) return false;
}
vis[u]=1;ans[--t]=u;
return true;
}
bool topo()
{
t=26;
for(int i=0;i<26;i++)
if(!vis[i])
if(!dfs(i)) return false;
return true;
}
int main()
{
int n,flag;
cin>>n;
init();
for(int i=0;i<n;i++)
cin>>s[i];
for(int i=1;i<n;i++)
{
flag=0;
int l=s[i-1].length(),ll=s[i].length();
for(int j=0;j<min(l,ll);j++)
{
if(s[i-1][j]!=s[i][j])
{
g[s[i-1][j]-'a'][s[i][j]-'a']=1;
flag=1;
break;
}
}
if(!flag)
{
if(l>ll)
{
cout<<"Impossible"<<endl;
return 0;
}
}
}
if(topo())
for(int i=0;i<26;i++)
cout<<(char)(ans[i]+'a');
else cout<<"Impossible"<<endl;
return 0;
}