拓扑排序(topological sort)

﹥>﹥吖頭↗ 提交于 2020-01-16 13:29:33

一、定义:

对一个有向无环图(Directed Acyclic Graph简称DAG) G进行拓扑排序

是将G中所有顶点排成一个线性序列

使得图中任意一对顶点u和v

若边(u,v)∈E(G)

则u在线性序列中出现在v之前

注意:

有时候,这里的排序不是唯一的

 

二、算法 O(V+E)

有两种:入度表、dfs

 

(一)、入度表  O(V+E):

 

找出图中0入度的点

依次在图中删除这些点

于是再找删掉点之后的0入度的点

然后再删除...再找点

 

入度为0的点 用 队列

图 用 邻接表

 

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

const int maxn = 10005;
int n,m,cnt;//cnt存储ans数组的下标
bool a[maxn][maxn];//邻接矩阵 
int  edge[maxn],ans[maxn];//edge[i]第i个点的入度,ans答案队列 
queue<int> q;

void topo_sort()
{
    for(int i = 1;i <= n;i++)
        if(!edge[i])
            q.push(i);//将所有入度为0的点加入队列中 
    while(!q.empty())
    {
        const int u = q.front();
        ans[++cnt] = u;
        q.pop();
        for(int i = 1;i <= n;i++)
            if(a[u][i])
            {
                edge[i]--;
                if(!edge[i])
                    q.push(i);
            } 
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        a[x][y] = 1;
        edge[y]++;
    }
    topo_sort();
    if(cnt < n)
    {
        printf("有环\n");
        return 0;
    } 
    for(int i = 1;i <= n;i++)
        printf("%d ",ans[i]);
    return 0;
}

 

 

 

(二)、dfs O(n2

(又要咕咕咕了...也不知道要咕多久qwq)

(洛谷居然出了一片日报,嘎!)

 (dfs只能判断有没有还环??!(hushuobadao

 

用一个int类型的visit数组 标记节点

其中-1表示回到自己(即 产生了环) 这届return

否则,跑一边这个图,跑完了就没有环

//拓扑排序dfs(只判断是否有环
#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 10005;
int n,m;
bool a[maxn][maxn];//邻接矩阵建图
bool flag;//判断是否有环,有环就true 
int vis[maxn];//标记节点,注意是int类型,因为要用到-1,1,0 

void dfs(int k)
{
    vis[k] = -1;//特殊标记
    for(int i = 1;i <= n;i++)
    {
        if(vis[i] == 0 && a[k][i] == true)
        {
            dfs(i);
            vis[i] = 1;
        }
        if(vis[i] == 1 && a[k][i] == true)
        {
            printf("有环\n");
            flag = true;
            return;
        }
    } 
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        a[x][y] = true;
    } 
    dfs(1);
    if(!flag)
        printf("无环\n");
    return 0;
} 

 

(我..算不算没gu很久wa.)

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!