算法图论学习-拓扑排序

183 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

什么是拓扑排序

对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边<u,v>∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序

拓扑排序的代码实现

我们记录每个点的出度如果这个点的出度为0那么就以为这个点在我们之后的拓扑图中是在最下面的,我们用队列去处理这个操作,出度先为0的先出让后将与它有连边的点的出度减一最后就形成了一个完整的拓扑图

void dfs() {
    queue<int> q;
    rep(i,n) if(de[i] == 0) q.push(i);
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        ++ cnt;
        for(auto x : v[t]) {
            de[x] -- ;
            ans[x] = max(ans[x],ans[t] + 1);
            if(de[x] == 0) q.push(x);
        }
    }
}

[拓扑排序例题](字典序最小拓扑序 - 题目 - Daimayuan Online Judge)

const int N = 2e5 + 10;
vector<int> v[N];
int de[N];
int n,m;
int cnt;
vector<int> ans;
void dfs() {
    priority_queue<int,vector<int>,greater<int>> q;
    rep(i,n) if(de[i] == 0) q.push(i);
    while(q.size())
    {
        auto t = q.top();
        ans.pb(t);
        q.pop();
        ++ cnt;
        for(auto x : v[t]) {
            de[x] -- ;
            if(de[x] == 0) q.push(x);
        }
    }
}
void solve()
{
   cin >> n >> m;
   rep(i,m) {
    int x,y; cin >> x >> y;
    v[x].pb(y);
    de[y]++;
   }
   dfs();
   for(auto x : ans) cout << x << ' ';
}