拓扑排序(邻接表+队列优化)

邻接矩阵的算法

之前做过一道dp+拓扑的题,用到了邻接表+队列的拓扑,

后来忘写博客了(大概好久以前了),今天补上

因为拓扑排序的答案是不唯一的,所以我们可以把所有入度为0的点都先放到队列里面,然后对于队列中的每一个点找它存储在邻接表里相邻的其它点,使其入度减一,经过这样的操作可以达到O(n+e)的复杂度。

当题目中要求特定输出顺序的时候,比如优先输出节点小的,我们就可以把队列改为优先队列来达到要求。

如果要判断环,可以用一个cnt统计入队列的点的个数,如果cnt<n(点的个数),那么就有环.

代码如下:

vector<int>v[MAXL+50];
int num[MAXL+50];
int n,m;
int ans[MAXL+50];
void toposort()
{
    priority_queue<int,vector<int>,greater<int> >q;//当要求编号小的优先输出时用优先队列存储点
    for(int i=1;i<=n;i++)
        if(!num[i])
            q.push(i);
    int len=0;
    while(!q.empty())
    {
        int u=q.top();
        q.pop();
        ans[len++]=u;
        for(int i=0;i<v[u].size();i++)
        {
            int t=v[u][i];
            num[t]--;
            if(!num[t])
                q.push(t);
        }
    }
    cout<<ans[0];
    for(int i=1;i<len;i++)
        cout<<" "<<ans[i];
    cout<<endl;
}
int main()
{
    while(cin>>n>>m)
    {
        memset(num,0);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            cin>>x>>y;
            num[y]++;
            v[x].push_back(y);
        }
        toposort();
        for(int i=0;i<=n;i++)
            v[i].clear();
    }
}

例题:HDU 1285 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define eps 1e-8
#define memset(a,v) memset(a,v,sizeof(a))
using namespace std;
typedef long long int LL;
const int MAXL(1e5);
const int INF(0x7f7f7f7f);
const int mod(1e9+7);
int dir[4][2]= {{-1,0},{1,0},{0,1},{0,-1}};
vector<int>v[MAXL+50];
int num[MAXL+50];
int n,m;
int ans[MAXL+50];
void toposort()
{
    priority_queue<int,vector<int>,greater<int> >q;
    for(int i=1;i<=n;i++)
        if(!num[i])
            q.push(i);
    int len=0;
    while(!q.empty())
    {
        int u=q.top();
        q.pop();
        ans[len++]=u;
        for(int i=0;i<v[u].size();i++)
        {
            int t=v[u][i];
            num[t]--;
            if(!num[t])
                q.push(t);
        }
    }
    cout<<ans[0];
    for(int i=1;i<len;i++)
        cout<<" "<<ans[i];
    cout<<endl;
}
int main()
{
    while(cin>>n>>m)
    {
        memset(num,0);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            cin>>x>>y;
            num[y]++;
            v[x].push_back(y);
        }
        toposort();
        for(int i=0;i<=n;i++)
            v[i].clear();
    }
}

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/Akatsuki__Itachi/article/details/80443778
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞