• 拓扑排序


    初学:

     常用来表示事件之间的依赖关系,任务之间的调度

    典型:依赖处理

    在图论上,他是把DAG生成一个线性数列,表示这个图顶点之间的先后关系

    过程

    1. 建立一个空队列,把所有入度为 0 的加入队列
    2. 然后从队列中取出一个节点,把该节点所有的出边删除,即入度 -1, 再判断该边通向的节点是否已经没有边连入(即入度是否为 0 ),若是,加入队列
    3. 重复,直到队列中不剩下任何节点

    注:拓扑排序是对于DAG而言。如果需要判断图中是否存在环, 可以统计是否所有的节点都入过队。存在未入队的节点,代表存在环(无法拓扑排序) (因为入度不可能为0

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 #define MAXN 1111
     5 #define MAXM 121111
     6 
     7 int n, m, cnt;
     8 int head[MAXN], q[MAXN], ru[MAXN];
     9 
    10 struct edge {
    11     int y, next;
    12 }e[MAXM];
    13 
    14 void add_edge(int x, int y) {
    15     e[++cnt].y = y;
    16     e[cnt].next = head[x];
    17     head[x] = cnt;
    18     return ;
    19 }
    20 
    21 int main() {
    22     scanf("%d%d", &n, &m);
    23     for(int i = 1; i <= m; i++) {
    24         int x, y;
    25         scanf("%d%d", &x, &y);
    26         ru[y]++;
    27         add_edge(x, y);
    28     }
    29     int l = 1, r = 0;
    30     for(int i = 1; i <= n; i++) {//入队 
    31         if(!ru[i]) {
    32             r++;
    33             q[r] = i;
    34         }
    35     }
    36     while(l <= r) {//一直while到q里没元素 
    37         int now = q[l];
    38         l++;//首元素出队
    39         for(int i = head[now]; i; i = e[i].next) {
    40             int y = e[i].y;
    41             ru[y]--;//终点为y的线段 入度——
    42             if(!ru[y]) {//如果入度减到了零 ,就让它进队(从后面入) 
    43                 q[++r] = y;
    44             }
    45         }
    46     }
    47     for(int i = 1; i <= m; i++) printf("%d ", q[i]);//队列前m个是已经拓扑排序好了的元素 
    48     return 0;
    49 }

    另一种亲民的做法(STL大法好,真善...

    int n,m;
    queue <int> q;
    for(int i = 1; i <= n; i++) if(ru[i] == 0) q.push(i);
    vector<int> ans;
    while(!q.empty()) {
        int u = q.front() ; q.pop() ;
        ans.push_back(u);
        for(int i = 0; i < G[u].size(); i++) {
            int v = G[u][i];
            ru[v]--;
            if(ru[v] == 0) {
                q.push(v); 
            }
        } 
    }
     if(ans.size()==n) {
        for(int i=0;i<ans.size();i++)
            printf( "%d ",ans[i] );
            printf("
    ");
        } else printf("No Answer!
    ");   
        // ans 中的长度与n不相等,就说明无拓扑序列

    相关题目

    1. 要求字典序最小

    解决方法: 改为优先队列即可

                    2153: D.ly的排队问题
                Time Limit: 1 Sec  Memory Limit: 128 MB

    Description
    马上要上体育课了,上体育课之前总归是要排个队的,ly作为班长,怎么排队的问题只能由她来解决,但是马上要上课了,ly又不清楚所有人的身高,她又不好意思问每个人的身高,因为这样会显的自己很不负责,于是她只能通过肉眼观察...那么问题来了,她只能观察出两个人A和B谁高谁矮,但是她没有办法排出一个序列。
    ly都已经帮你出了两次主意赢过wjw,那么现在她需要你的帮助,你可以帮她吗?
    (ly会告诉你A和B谁高,如果A比B高,会用A>B来表示)

    Input
    只有一组数据,每个比较结果占一行,读取到文件结束

    Output
    若输入数据无解,则输出"No Answer!",否则从高到低输出每个人的名字,中间没有分割符
    若有多种情况,输出字典序最小的答案

    Sample Input
    E>A
    A>S
    S>Y
    Sample Output
    EASY

    注: 这里的目的只是引入字典序最小该怎么做,具体的题解实际上是有点问题的

    如: A>B B<C C<D 结果实际上是判断不出身高的(阔以自己试试

    #include<cstdio>
    #include<queue>
    #include<set>
    #include<vector>
    #include<iostream>
    using namespace std;
    
    
    int main() {
        set <int> s;
        int ru[30] = {0};
        vector <int> v[30];
        char tmp[5];
    //    while(cin>>tmp) {
        while(~scanf("%s",tmp)) {
            s.insert(tmp[0]-'A');
            s.insert(tmp[2]-'A');
            if(tmp[1] == '>') {
                ru[tmp[2]-'A']++;
                v[tmp[0]-'A'].push_back(tmp[2]-'A'); 
            } else {
                ru[tmp[0]-'A']++;
                v[tmp[2]-'A'].push_back(tmp[0]-'A'); 
            }
        }
        priority_queue <int,vector<int>,greater<int> > q;
        for(int i = 0; i < 30; i++) if(ru[i]==0 && s.count(i) != 0) q.push(i);
        vector <int> ans;
        while(!q.empty()) {
            int now = q.top() ; q.pop() ;
            ans.push_back(now); 
            for(int i = 0; i < v[now].size() ; i++) {
                int y = v[now][i];
                ru[y]--;
                if(ru[y] == 0&&s.count(y)!=0) q.push(y); 
            }
        }
        if(ans.size() != s.size() ) printf("No Answer!");
        else for(int i = 0; i < ans.size() ; i++) printf("%c",ans[i]+'A');
        printf("
    ");
        return 0;
    } 
    /*
    A>B
    B<C
    C<D
    */

     

     参考代码

    自己选择的路,跪着也要走完。
  • 相关阅读:
    opencv 遍历Mat对象中数据方法-转
    JVM OutOfMemoryError 分析
    hibernate validation HV000030: No validator could be found for constraint
    通过aop实现rpc统一参数校验&异常捕捉
    java8 lambda groupingby 分组保持原来顺序
    递归判断素组是否有序
    dubbo 直连
    Linux 删除openjdk
    telnet命令调用远程dubbo 接口
    git submodule ssh key
  • 原文地址:https://www.cnblogs.com/tyner/p/10701729.html
Copyright © 2020-2023  润新知