拓扑排序:偏序变成全序的过程。
具有自反性,反对称性,传递性的集合叫偏序。
今天翻看数据结构课本上,看到拓扑排序了,有两种方法,一种是找入度为零的点,然后删除相连的变,再找初度为0的点,入栈,知道找不到,另一种是有向无环图时候,可以用dfs退栈的方法,搜到最后的那个点,就是初度为0的点了,即可用一个数组存上,最后倒序输出这个数组就是拓扑排序了,如果有换的情况下,参考算法导论上的染色问题,即可解决,我找了个别人写的模版:
利用dfs的方法就是找搜索树种的回边,利用染色的方法,算法导论上有介绍
我写的代码如下:
初始化:memset(vis,0,sizeof(vis));
对所有vis[i] == 0,调用dfs
bool dfs(int u)
{
if(vis[u] == 1) return false;
if(vis[u] == 2) return true;
vis[u] = 1;
for(i = 0;i < g[u].size();i++) {
if(false == dfs(g[u][i])) {
return false;
}
}
vis[u] = 2;
stack[top++] = u;
return true;
}
下面是我在poj上找的一道题,拿来做个参考。我觉得可以留给考研复习的同学们用,哈哈
Source Code
Problem: 2367 | User: xingkaka | |
Memory: 188K | Time: 0MS | |
Language: C++ | Result: Accepted |
- Source Code
#include<iostream> #include<stdio.h> using namespace std; #include<vector> #define MAZ 105 int vis[MAZ]; int g[MAZ]; int f=0; vector<int>m[MAZ]; void dfs(int v) { if(vis[v])return ; vis[v]=1; for(int i=0;i<m[v].size();i++) { if(!vis[m[v][i]])//这里也可以不写 dfs(m[v][i]); } g[f++]=v; } int main() { int n,i,j; scanf("%d",&n); for(i=1;i<=n;i++) { int v; while(scanf("%d",&v)!=EOF&&v!=0) { m[i].push_back(v); } } for(i=1;i<=n;i++) { if(!vis[i]) { dfs(i); } } for(i=f-1;i>=1;i--) printf("%d ",g[i]); printf("%d\n",g[0]); return 0; }