拓扑排序详解 (?

拓扑排序详解

定义

什么是拓扑排序?

拓扑排序就可以理解为如果要访问i点,之前必须访问j点,给出一个合法的访问顺序,联系到生活中就可以理解为你要泡茶,但你之前必须烧水。那么烧水-泡茶就是一种合理的拓扑排序。 (够形象了吧

实现

探寻规律的话,发现tp(自创简称懒得打字)里的第一件事一定是不需要之前做什么事情的,此时做完了之后你应该做下面一件事,做完的事情不考虑,接下来同上,就能发现规律。

联系到图上,怎么tp? (假设有向图上i点能到j点为i需要在j点之前完成)

每次寻找一个入度为0的点,将其输出,然后把能到达的节点入度减一,如果还有入度为0的继续。

(不要以为这样就结束了 , 想想一个图的tp一定存在吗?)

当然,图中出现环的时候此时一定没有tp , 如何判断? (这个方法很多,最简单的就是判断拓扑序列长度小于节点个数就没有拓扑排序

例子

拓扑排序详解 (?

从1出发,砍掉入度,发现2为0,继续,发现4为0,继续最后是3. PS://一开始就要把所有入度为0的全部入队,如果有多个连通块呢?


话不多说上代码

#include <bits/stdc++.h>
using namespace std;
int indgree[1000];
vector<int> g[1000];
int n, m;
vector<int> seq;
// 邻接表大法好
// seq 存储拓扑
void top() {
  queue<int> q;
  for (int i = 0; i <= n - 1; ++i) {
    if (indgree[i] == 0) {
      q.push(i);
    }
  }
  while (!q.empty()) {
    int cur = q.front();
    seq.push_back(cur);
    q.pop();
    for (int i = 0; i < g[cur].size(); ++i) {
      --indgree[g[cur][i]];
      if (indgree[g[cur][i]] == 0) {
        q.push(g[cur][i]);
      }
    }
  }
  if (seq.size() != n) {
    cout << "NO" << endl;
  } else {
    cout << "YES" << endl;
  }
}
int main() {
  freopen("legal.in", "r", stdin);
  freopen("legal.out", "w", stdout);
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    g[x].push_back(y);
    ++indgree[y];
  }
  top();
}

(觉得不烂的给个三连吧 (走错片场了抱歉,给个好评吧

上一篇:Minimum Sum(平面对近点对+分治)


下一篇:压缩感知与稀疏模型——Convex Methods for Sparse Signal Recovery