• 拓扑排序


     拓扑排序

    toposort

    前置知识

    1.  DAG  :  有向无环图

    2.AOV网,AOE网

     这两个概念都是用来描述和分析一项工程的计划和实施过程的。注意都是有向图。

    (1)AOV:Activity On Vertex Network,把每个顶点作为一项活动,把两个顶点间的边作为活动间的相互关系。看下面的例子:

    活动1,2,3可以直接开始,但活动4必须在3完成后开始,5必须在1,2,3都完成后开始,6必须在1,2,5完成后开始。

    (2)AOE:Activity On Edge Network,把每条边作为一项活动,通常还会有权值(长度),把每个顶点作为作为一种状态,所以只会有一个起点和一个终点。看下面的例子:

     

    从1开始,在时刻3可以到达2,但想要到达3,必须两个指向它的边都完成,所以在时刻5可以到达3。以此类推。

     

     3.度

         一个点连着的边的数量,称为该点的度。其中由该点出发的称为出度,到达该点的称为入度。

     

     

     

    拓扑排序

    基本概念

            对于一个DAG,请给定一个所有结点的排列,使得图中每条边的起点都比终点在该排列中的位置靠前。

           实质作用是给AOV网或AOE网给定一个可行的完成任务的先后顺序(此处假定一个时刻只能完成一个任务)。

    代码实现

    BFS实现

    1. 把所有入度为0的点入队

    2. 循环直到队列为空

    3. 队首元素h出队,并加入拓扑序

    4. 对h所有可以到达的点,入度减一,若这时该点入度为零,让它入队

    5. 若循环结束时拓扑序长度不为节点个数,则证明图中有环,即不是DAG,意味着不存在拓扑序,这时(在大部分情况下),你应该输出无解

    JUST LIKE THIS

    0  2  入度为零,先开始分离它们,也就是把他们的出边去掉

    最后他们就都给分离完了,都搁这飘着

     

     

    但是你如果遇到一个环

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int maxn=10000;
    int n,m;
    int head[maxn],next[maxn],in[maxn],to[maxn],cnt=0;
    int ans[maxn],cntans=0;
    
    void add(int start,int end)
    {
        cnt++;
        to[cnt]=end;
        next[cnt]=head[start];
        head[start]=cnt;
        
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        int u,v;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v);
            in[v]++;
        } 
        
        priority_queue<int,vector<int>,greater<int> >q;
        
        for(int i=1;i<=n;i++)
        {
            if(!in[i]) q.push(i);
        }
        
        while(!q.empty())
        {
            int now=q.top();
            q.pop();
            ans[++cntans]=now;
            for(int e=head[now];e;e=next[e])
            {
                in[to[e]]--;
                if(!in[to[e]])
                q.push(to[e]);
            }
        }
        
        if(cntans!=n) printf("I AKIOI !!!");
        else
        {
            for(int i=1;i<=cntans;i++)
              printf("%d
    ",ans[i]);
        }
        
        return 0;
    } 

    DFS实现  <liao jie yi xia pa>

    这个算法看起来很简单,但实际却不好写。

    1.从某个入度为0的点出发DFS

    2.递归处理所有可以到达的点

    3.将该点加入拓扑序

    4.全部DFS结束后,将求出来的序列翻转,即为拓扑序

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int max_n = 100001, max_m = 100001;
    int fir[max_n], to[2 * max_m], nxt[2 * max_m], ecnt;
    void add(int u, int v)
    {
        to[++ecnt] = v;
        nxt[ecnt] = fir[u];
        fir[u] = ecnt;
    }
    int in[max_n];
    int n, m;
    int ans[max_n], anscnt;
    int vis[max_n]; //0:not visited  1:visited  -1:is visiting
    bool dfs(int node)
    {
        vis[node] = -1;
        for (int e = fir[node]; e; e = nxt[e])
        {
            if (vis[to[e]] == 1)
                continue;
            if (vis[to[e]] == -1 || dfs(to[e]) == false)
                return false;
        }
        vis[node] = 1;
        ans[++anscnt] = node;
        return true;
    }
    int main()
    {
        cin >> n >> m;
        for (int i = 1; i <= m; i++)
        {
            int u, v;
            cin >> u >> v;
            add(u, v);
            in[v]++;
        }
        for (int i = 1; i <= n; i++)
        {
            if (in[i] == 0 && vis[i] == 0)
            {
                if (dfs(i) == false)
                {
                    break;
                }
            }
        }
        if (anscnt != n)
        {
            cout << "I AKIOI !!!
    ";
        }
        else
        {
            for (int i = n; i >= 1; i--)
            {
                cout << ans[i] << ' ';
            }
            cout << endl;
        }
    }

    最后安利一个画图网站:

    https://csacademy.com/app/graph_editor/

    QWQ  画出来是一个会游动的图  它很皮

    最最后感谢 water lift 的讲解以及课件和代码QWQ

  • 相关阅读:
    magento设置快捷支付后,付款出现Unable to communicate with the PayPal gateway
    Magento安装插件失败出现503错误的解决方法
    magento安装插件后显示404error
    magento安装插件报connection string is empty
    mysql修改root密码
    thinkphp 3.2.3版本学习笔记
    那些年,被我蠢哭了的php代码小错误~~~
    PHP实现文件上传和下载(单文件上传、多文件上传、多个单文件上传)(面向对象、面向过程)
    php生成纯数字、字母数字、图片、纯汉字的随机数验证码
    php使用GD库实现图片水印和缩略图——封装成类
  • 原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/11072431.html
Copyright © 2020-2023  润新知