拓扑排序

拓扑序列

对一个有向无环图(Directed Acyclic Graph,简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前

AOV网(顶点活动网,Activity On Vertex network):顶点表示活动、边表示活动间先后关系的有向图。

Kahn算法

算法步骤

主要是循环执行以下两步,直到不存在入度为0的顶点为止。

(1) 选择一个入度为0的顶点并输出之;

(2) 从网中删除此顶点及所有出边。

循环结束后,若输出的顶点数小于网中的顶点数,则有回路,否则输出的顶点序列就是一种拓扑序列。

class Edge{
    int to;
    int cost;
}
class AOV{
    int N;
    int M;
    Vector<Edge>[] graph;
    int[] degree;
    LinkedList<Integer> topology;//FIFO
    void init(){
        graph = new Vector[N];
        degree = new int[N];
        topology = new LinkedList<Integer>();
        for (int i = 0; i < N; i++)
            graph[i] = new Vector<Edge>();
    }
    boolean Kahn(){
        Stack<Integer> stack = new Stack<Integer>();//storage the nodes of which degree is 0
        for (int i = 0; i < N; i++) {
            if(0 == degree[i])
                stack.push(i);
        }
        int now = 0;
        while (!stack.isEmpty()){
            now = stack.pop();
            topology.add(now);
            for (int i = 0; i < graph[now].size(); i++) {
                Edge edge = graph[now].get(i);
                degree[edge.to]--;
                if(0 == degree[edge.to])
                    stack.push(edge.to);
            }
            graph[now].clear();
        }
        if(topology.size() == N){
            return true;
        }else
            return false;
    }
}

基于DFS的拓扑排序

每次都沿着一条路径一直往下搜索,直到某个顶点没有了出度时,就加入拓扑序列中,然后往回走,所以我们就用DFS的这个思路,我们可以得到一个有向无环图的拓扑序列,其实很像Kahn算法的逆过程。

#include<iostream>
#include<stack>
using namespace std;
#define Max 9999
int graph[Max][Max];//一个有向图
int n,m;//结点数,边数
stack<int> topo;//栈存拓扑序列,先进后出
int vis[Max];//访问状态:-1正在访问,1访问结束,0未访问
bool dfs(int u)
{
    vis[u]=-1;//正在访问
    int i;
    for(i=1;i<=n;i++)
        if(graph[u][i]==1)//找边
        {
            if(vis[i]==-1)//访问两次,说明有环
                return 0;
            else
                if(vis[i]==0)//未访问过
            dfs(i);
        }
    vis[u]=1;//访问完成
    topo.push(u);//将该点入栈
    return true;
}
bool Topological_sort()
{
    for(int i=1;i<=n;i++)//遍历每个结点
        if(vis[i]==0)//未访问过
        {
            if(!dfs(i))
                return false;
        }
    return true;
}
int main()
{
    int u,v;
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        cin>>u>>v;
        graph[u][v]=1;
    }
    if(Topological_sort())//无环,输出拓扑序列
    {
        int size=topo.size();
        for(int i=0;i<size;i++)
        {
            cout<<topo.top()<<" ";
        topo.pop();
        }
        cout<<endl;
    }
    else
        cout<<"有环"<<endl;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值