[拓扑排序]

拓扑排序

在一个有向图中,对所有的节点进行排序,要求没有一个节点指向它前面的节点

具体实现

1

找到一个入度为0的点

2

把这个点删掉(放入ans中),把所有以他为起点的路断掉

3

重复 1 2 直到没有入度为0的点 如果还有点没有被删掉 那就是有环(所以还可以用来判断图里是否有环)

ans中的顺序就是拓扑排序后的顺序

下面这个图表现的更明显

代码实现

1 首先看到“具体实现”我们先考虑模拟

好理解,好写,效率低

所以我们不写了

2 在搞完模板题后,看到正确的打开方式应该是 queue

模板题:HDU-1285

vector实现

因为是要求编号尽量从小到大,所以这里的queue要用优先队列

而且要用priority_queue<int, vector, greater > q; 就要加一个头文件 #include<functional>

我们记下每个点的入度是多少,先找到一个入度为0的点,放入queue中,然后循环取top,把所有以他为起点的路断掉,终点入度-1,当前点放到ans中,如果这个点入度为0了,再扔进queue

#include <stdio.h>
#include<string.h>
#include<functional>
#include<queue>
#include<vector>
using namespace std;
#define ll long long
#define lowbit(a) ((a) & -(a))
#define clean(a, b) memset(a, b, sizeof(a))
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 9;

int _;

//========================================================================
int vis[509];
priority_queue<int, vector<int>, greater<int> > q;
vector<int>ans;
vector<int>edge[509];
void topological_sort(int n)
{
    while(!q.empty()) q.pop();
    ans.clear();
    for(int i=1;i<=n;i++)
    {
        if(vis[i]==0) q.push(i);
    }
    while(!q.empty())
    {
        int now=q.top();
        q.pop();
        ans.push_back(now);
        int len=edge[now].size();
        for(int i=0;i<len;i++)
        {
            int p=edge[now][i];
            vis[p]--;
            if(vis[p]==0) q.push(p);
        }
    }
    int len=ans.size();
    for(int i=0;i<len;i++) printf("%d%s",ans[i],i!=n-1?" ":"");
    printf("\n");
}
//========================================================================
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        clean(vis,0);
        for(int i=1;i<=m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            edge[u].push_back(v);
            vis[v]++;
        }
        topological_sort(n);
        for(int i=1;i<=n;i++) edge[i].clear();
    }
    return 0;
}

链式前向星实现

(都差不多,但我很久没用链式前向星了,复习一下)


#include <stdio.h>
#include<string.h>
#include<functional>
#include<queue>
#include<vector>
using namespace std;
#define ll long long
#define lowbit(a) ((a) & -(a))
#define clean(a, b) memset(a, b, sizeof(a))
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 9;

int _;

//========================================================================
int vis[509];
priority_queue<int,vector<int>,greater<int> > q;
vector<int>ans;
struct edge
{
    int to,cost,next;
}e[maxn];
int top,head[maxn];
void init()
{
    top=0;
    memset(head,-1,sizeof(head));
}
void insert_(int u,int v,int c)
{
    e[top].to=v;
    e[top].cost=c;
    e[top].next=head[u];
    head[u]=top++;
}
void topological_sort(int n)
{
    while(!q.empty()) q.pop();
    ans.clear();
    for(int i=1;i<=n;i++)
    {
        if(vis[i]==0) q.push(i);
    }
    while(!q.empty())
    {
        int now=q.top();
        q.pop();
        ans.push_back(now);
        for(int i=head[now];i!=-1;i=e[i].next)
        {
            int p=e[i].to;
            vis[p]--;
            if(vis[p]==0) q.push(p);
        }
    }
    int len=ans.size();
    for(int i=0;i<len;i++) printf("%d%s",ans[i],i!=n-1?" ":"");
    printf("\n");
}
//========================================================================
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        clean(vis,0);
        for(int i=1;i<=m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            insert_(u,v,1);
            vis[v]++;
        }
        topological_sort(n);
    }
    return 0;
}
posted @ 2020-07-06 23:45  L·S·D  阅读(140)  评论(0编辑  收藏  举报