#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#define FAST ios::sync_with_stdio(false)
#define LL long long
using namespace std;
const int N = 1e5 + 10;
int Head[N],tot,st[N],n,m,indegree[N];
stack<int> s; // 用来存当前入度为0的顶点的序号
struct E{
int to,next;
}Edge[N];
void add(int a,int b) // 读入边的操作
{
Edge[tot].to = b;
Edge[tot].next = Head[a];
Head[a] = tot ++;
}
int find_du(void) // 遍历确定图中每一个点的入度
{
for(int i = 1;i <= n;i++)
{
for(int j = Head[i] ; j != -1 ; j = Edge[j].next)
{
indegree[Edge[j].to] ++;
}
}
}
vector<int> Topsort()
{
for(int i = 1;i <= n;i++)
{
if(indegree[i] == 0)
{
s.push(i);
}
} // 先存入初始的时候度就为 0 的点
int count = 0; // 用来记录当前确定了拓扑序列的点的数目
vector<int> ans;
while(!s.empty()) // 每次取出一个入度为0的点,同时删去与这个点有关的所有边,创造新的入度为0的边
{
int temp = s.top();
count ++ ;
s.pop();
ans.push_back(temp);
for(int i = Head[temp] ; i != -1 ; i = Edge[i].next)
{
indegree[Edge[i].to] -- ; // 删除以这个点为起点的终点的顶点入度
if(indegree[Edge[i].to] == 0) s.push(Edge[i].to); // 检查是否有新的入度为0的点产生
}
}
if(count == n) // 这个图中的所有的顶点都可以确定其的拓扑序列位置
{
cout << "Yes" << endl;
return ans;
}
else
{
cout << "No" << endl;
ans.clear();
return ans;
}
}
int main(void)
{
FAST;
memset(Head,-1,sizeof Head);
cin >> n >> m;
while(m --)
{
int a,b;
cin >> a >> b;
add(a,b); // 有向无环图
}
find_du();
vector<int> Top = Topsort();
for(auto it : Top) cout << it << " ";
return 0;
}
拓扑排序 + 链式前项星 (教材版本实现)
最新推荐文章于 2021-03-05 17:51:17 发布