晕牛【拓扑排序】【BFS】

题目大意:
这里写图片描述
I n p u t

4 2 3
1 2
4 3
1 3
4 2
3 2

O u t p u t

1 3
2 4
2 3

思路:

好题好题!

拓扑排序真的是一个轻轻松松学会的算法。

我们将单向道路按照拓扑排序排一下,然后读入双向边,将排在前面的指向排在后面的,输出,就。。。

AC了!

具体原理我也不太清楚,还是去问那个某dalao吧。


代码:

#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;

int n,m1,m2,x,y,tot,head[300001],vis[300001],num[300001],t[300001],o[300001];

struct edge
{
    int next,to;
}e[300001];

void fre()
{
    freopen("dizzy.in","r",stdin);
    freopen("dizzy.out","w",stdout);
}

void add(int from,int to)
{
    tot++;
    e[tot].to=to;
    e[tot].next=head[from];
    head[from]=tot;
}

void bfs()
{
    int k=0;
    queue<int> q;  //队列
    for (int i=1;i<=n;i++)
     if (!num[i])  //没有入度
     {
        q.push(i);  //加入队列
        t[++k]=i;  //记录
     }
    do
    {
        int u=q.front();
        q.pop();
        for (int i=head[u];i;i=e[i].next)  //邻接表
        {
            int v=e[i].to;
            num[v]--;   //入度减一
            if (!num[v])  //没有入度
            {
                q.push(v);  //入队
                t[++k]=v;
            }
        }
    }
    while (q.size());
}

int main()
{
    fre();
    scanf("%d%d%d",&n,&m1,&m2);
    for (int i=1;i<=m1;i++)
    {
        scanf("%d%d",&x,&y);
        num[y]++;  //求最大入度,为拓扑排序初始化
        add(x,y);  //邻接表
    }
    bfs();
    for (int i=1;i<=n;i++)
     o[t[i]]=i;
    for (int i=1;i<=m2;i++)
    {
        scanf("%d%d",&x,&y);
        if (o[x]<o[y]) printf("%d %d\n",x,y);  //O(1)输出
          else printf("%d %d\n",y,x);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ssl_zyc/article/details/80969592