模板
拓扑排序 ------ 模板题 AcWing 848. 有向图的拓扑序列
时间复杂度 O(n+m), n 表示点数,m 表示边数
bool topsort()
{
int hh = 0, tt = -1;
// d[i] 存储点i的入度
for (int i = 1; i <= n; i ++ )
if (!d[i])
q[ ++ tt] = i;
while (hh <= tt)
{
int t = q[hh ++ ];
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if (-- d[j] == 0)
q[ ++ tt] = j;
}
}
// 如果所有点都入队了,说明存在拓扑序列;否则不存在拓扑序列。
return tt == n - 1;
}
N 个小朋友,编号 1∼N,要排成一队。
在安排每个人的顺序时,有 M个要求,每个要求包含两个整数 a,b,表示小朋友 a 要排在小朋友 bb 的前面。
请你找出符合所有要求的排队顺序。
输入格式
第一行包含整数 N,M。
接下来 M行,每行包含两个整数 a,b。
输出格式
按排好队列从前到后的顺序在一行内输出每个小朋友的编号。
保证至少存在一个符合条件的顺序。
当符合条件的排队顺序不唯一时,编号更小的小朋友尽量更靠前。
数据范围
1≤N≤500,
1≤M≤5000,
1≤a,b≤N,
保证数对 (a,b)各不相同。
输入样例:
4 3
1 2
2 3
4 3
输出样例:
1 2 4 3
///拓扑排序
//先构造图,有向图
//进行拓扑排序
//每次选择入度是0的节点,如果不止一个,找到最小的
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int N=510,M=5010;
int ha[N],e[M],nx[M];
int idx;
int d[N];//入度
int n,m;
//将b添加到以节点a开头的邻接表中
void add(int a,int b){//添加一条a-->b的边
e[idx]=b;//第idx个边终点是b
nx[idx]=ha[a];//头插法
ha[a]=idx;//头插法
idx++;//地址
}
void topsort(){
priority_queue<int,vector<int>,greater<int>> heap;
for(int i = 1;i <= n ; i++){
if(!d[i]) heap.push(i);
}
while(heap.size()){
auto t = heap.top();
printf("%d ",t);
heap.pop();
for(int i = ha[t]; i!= -1; i=nx[i]){
int j = e[i];
if(--d[j]==0){
heap.push(j);
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
memset(ha,-1,sizeof(ha));//情况表头
int a,b;
for(int i = 1; i <= m; i++){
scanf("%d%d",&a,&b);//读边
d[b]++;
add(a,b);
}
topsort();
return 0;
}