拓扑排序详解(超详细+模板)

拓扑排序

1.什么是拓扑排序
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图
中任 意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序
(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操
作称之为拓扑排序。 无向图和有环的有向图没有拓扑排序拓扑排序其实就是离散上的偏序关系的一个应用
2、拓扑排序的步骤:
1.按照一定的顺序进行构造有向图,记录后个节点的入度; 2,从图中选择一个入度为0的顶点,输出该顶点; 3,从图中
删除该顶点及所有与该顶点相连的边 4,重复上述两步,直至所有顶点输出。 5或者当前图中不存在入度为0的顶点为
止。此时可说明图中有环。 6,因此,也可以通过拓扑排序来判断一个图是否有环。

举个栗子
拓扑排序详解(超详细+模板)_第1张图片
然后我们可以按照上面的操作得到如下的几套方案 0>1>2>3>4>5>6 1>0>2>3>5>4>6 0>1>3>5>2>4>4 等等一系列方案

4、拓扑排序模板

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
int in[10010];
vector<int> v[10010];
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m)&&n&&m)
    {
        memset(in,0,sizeof in);//清空入度
        for(int i=0;i<=n;i++) v[i].clear();
        for(int i=0;i<m;i++)
        {
            int x,y;
            cin >>x>>y;//比如x赢了y  或者y是x的儿子 ;那么就让x指向y;
            v[x].push_back(y);
            in[y]++;//y的入度加1
        }
        priority_queue<int,vector<int>,greater<int> >q;//优先队列,设置从小到大排序,小的在队列下面
        for(int i=0;i<n;i++)
        {
            if(in[i]==0)
                q.push(i);//把入度为0的节点压入队列
        }
        while(!q.empty())
        {
            int xx=q.top();
            q.pop();
            n--;//每次去掉一个节点
            for(int i=0;i<v[xx].size();i++)
            {
                int yy=v[xx][i];
                in[yy]--;
                if(!in[yy])
                    q.push(yy);//如果去掉上一个节点之后下一个节点的入度变为0,则压入队列中
            }
        }
        if(n) cout <<"NO"<<endl;//如果有环的话节点数不会为0
        else cout <<"YES"<<endl;
    }
    return 0;
}

你可能感兴趣的:(#,拓扑排序)