AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 其它
    • 题解
    • 分享
    • 商店
    • 问答
  • 吐槽
  • 登录/注册

拓扑排序

作者: 作者的头像   小张睡不醒 ,  2023-01-24 15:36:11 ,  所有人可见 ,  阅读 36


1


思路:

1. 看这个图是否有环,如果没有环就一定存在拓扑序列
2. 求出每个点的入度
3. 把所有入度为 0 的点入队
4. 枚举每一条边,删除它就是让 d[j] --;
5. 当入度为 0 时,说明前面的点都已经有序,将当前点入队
6. 当所有点都入队时说明存在拓扑序列
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;
}

微信图片_20230124135219.jpg
题目描述
给定一个 n 个点 m 条边的有向图,点的编号是 1 到 n,图中可能存在重边和自环。

请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出 −1。

若一个由图中所有点构成的序列 A 满足:对于图中的每条边 (x,y),x 在 A 中都出现在 y 之前,则称 A 是该图的一个拓扑序列。

样例
3 3
1 2
2 3
1 3
输出
123

#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n,m;
int h[N],e[N],ne[N],idx;
int q[N],d[N];

void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

bool topsort()
{
    int hh=0,tt=-1;
    for(int i=1;i<=n;i++)//把所有入度为0的点入队
        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];
             d[j]--;//入度减一
            if(d[j]==0)
            q[++tt]=j;
        }
    }

    //当所有点入队时,说明存在拓扑序列
    return tt==n-1;
}

int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof h);
    //建边,并且b的入度加1
    while(m--)
    {
        int a,b;
        cin>>a>>b;
        add(a,b);
        d[b]++;//a->b所以b的入度加一
    }

    //若为真,说明所有点都已入队
    if(topsort())
        for(int i=0;i<n;i++)
            cout<<q[i]<<' ';
    else cout<<-1<<endl;

    return 0;
}

2.STL

#include <bits/stdc++.h>
using namespace std;
const int N = 100010, M = N;
int n, m;
int h[N], e[M], ne[M], idx;
int d[N];  //入度
void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

void topsort() {
    queue<int> q;
    int ans[N], top = 0;
    for (int i = 1; i <= n; i++)
        if (!d[i]) q.push(i), ans[++top] = i;
    while (q.size()) {
        int t = q.front(); q.pop();
        for (int i = h[t]; ~i ; i = ne[i]) {
            int j = e[i];
            if (--d[j] == 0) q.push(j), ans[++top] = j;
        }
    }
    if (top != n) puts("-1");
    else for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
}


int main() {
    memset(h, -1, sizeof h);
    scanf("%d%d", &n, &m);
    while (m--) {
        int a, b; scanf("%d%d", &a, &b);
        add(a, b); d[b]++;
    }
    topsort();
    return 0;
}

0 评论

你确定删除吗?
1024
x

© 2018-2023 AcWing 版权所有  |  京ICP备17053197号-1
用户协议  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标
请输入绑定的邮箱地址
请输入注册信息