拓扑排序--代码

模板

常用代码模板3——搜索与图论 - AcWing

拓扑排序 —— 模板题 AcWing 848. 有向图的拓扑序列
时间复杂度 O(n+m), n 表示点数,m 表示边数。

//N是110,表示节点个数,M是边的个数
const int N = 1010,M=10100;
int h[N],nx[M],e[M],idx;//数组模拟邻接表
//添加从a到b的边
//实际上,就是将节点b放到节点a的邻接表中
void add(int a,int b){
    e[idx]=b;
    nx[idx]=h[a];
    h[a]=idx;
    idx++;
}
//遍历
/*


//从节点a开始遍历节点a的下面的邻接表
memset(h,-1,sizeof(h))
for(int i = h[a]; i != -1 ; i=nx[i]){
    //取出边
    int j = e[i];//根据地址编号i得到节点实际名称j
    //其他操作
}


*/

bool topsort()
{
    int hh = 0, tt = -1;//hh是队首,tt是队尾,从队尾入队,从队首出队

    // d[i] 存储点i的入度,存储入度大于0的点
    for (int i = 1; i <= n; i ++ )
        if (!d[i])//入度是0
            q[ ++ tt] = i;//++tt,队尾入队

    while (hh <= tt)//队q不为空
    {
        int t = q[hh ++ ];//出队hh++
        //找t开头的邻接表
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];//找到对应节点
            if (-- d[j] == 0)//入度减1
                q[ ++ tt] = j;//入队
        }
    }

    // 如果所有点都入队了,说明存在拓扑序列;否则不存在拓扑序列.
    return tt == n - 1;//如果tt是n-1,表明入队的数量是n,全部入队
}

3704. 排队 - AcWing题库

N 个小朋友,编号 1∼N,要排成一队。

在安排每个人的顺序时,有 M个要求,每个要求包含两个整数 a,b,表示小朋友 a 要排在小朋友 b的前面。

请你找出符合所有要求的排队顺序。

输入格式
第一行包含整数 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
#include
#include
#include


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,边b的存储编号是idx
    nx[idx]=ha[a];//头插法
    ha[a]=idx;//头插法
    idx++;//地址
}
void topsort(){
    //队列,存储入度是0的点,使用队列存储
    priority_queue,greater> heap;
    for(int i = 1;i <= n ; i++){
        if(!d[i]) heap.push(i);//入度是0的节点全部入队
    }
    while(heap.size()){heap.size()==0,是空;否则,不为空
        int  t = heap.top();//取队首元素
        printf("%d ",t);//输出
        heap.pop();//出队
        
        for(int i = ha[t]; i!= -1; i=nx[i]){//遍历头节点是t的邻接表
            int j = e[i];//取出相应的节点
            if(--d[j]==0){//入度减1,如果是入度是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;
}

你可能感兴趣的:(算法,数据结构)