拓扑排序 + 链式前项星 (教材版本实现)

#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值