拓扑排序(dfs)

问题:

  对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。(如下图)

思想:

  1.找到一个没有子节点的节点,他就是最后一个要做的事情。

  2.删除这个子节点。

  3.在当前图里再次寻找没有子节点的节点。

  4.删除到没有节点时,将删除顺序倒过来就是拓扑排序的顺序。

  补:如果已经找不到没有子节点的节点,说明这张图有环,不存在拓扑排序。

代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>

using namespace std;

const int maxn=1e3+10;
int G[maxn][maxn];
int n;
int c[maxn];
int topo[maxn],t;
bool dfs(int u){
    c[u]=-1;            //c[u]==-1表示正在查找这个点的子节点
    for(int v=0;v<n;v++)if(G[u][v]){
        if(c[v]<0)return false;
            //因为G[u][v]!=0才会进入这里,代表v时u的子节点。
            //c[v]==-1,代表正在查找v的子节点,说明u时v的子节点
            //说明u和v之间是一个环
        else if(!c[v]&&!dfs(v))return false;
            /*这句话理解为
                if(!c[v]){  //如果点v没有查找过,那么查找点v的子节点
                    if(!dfs(v)){ //如果v的子节点内存在环,返回false
                        return false;
                    }
                }
            */
    }
    c[u]=1;topo[--t]=u;//没有子节点的节点会最先到达这里
    return true;
}
bool toposort(){
    t=n;
    memset(c,0,sizeof(c));
    for(int u=0;u<n;u++)
        if(!c[u])
            if(!dfs(u))
                return false;
    return true;
}
int main()
{
    int m;
    memset(G,0,sizeof(G));
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        G[a][b]=1;
    }
    if(toposort())
    for(int i=0;i<n;i++){
        printf("%d ",topo[i]);
    }
    else printf(".....\n");
    return 0;
}

原文地址:https://www.cnblogs.com/wz-archer/p/10670788.html

时间: 2024-07-30 15:52:24

拓扑排序(dfs)的相关文章

poj 1270 Following Orders(拓扑排序+dfs)

大致题意:每个样例包含两行,第一行输入n个字符,可能是无序的.第二行输入成对的a b,代表a要在b前面.输出所有的符合这样的序列. 思路:很明显的拓扑排序.要输出所有的序列,那么就从入度为0的点进行dfs,每次选择一个入度为0的点,加入输出序列并把与它相邻的点的入度减一.dfs结束后要把状态再改回来. #include <stdio.h> #include <algorithm> #include <set> #include <map> #include

poj1270Following Orders(拓扑排序+dfs回溯)

题目链接: 啊哈哈,点我点我 题意是: 第一列给出所有的字母数,第二列给出一些先后顺序.然后按字典序最小的方式输出所有的可能性... 思路: 总体来说是拓扑排序,但是又很多细节要考虑,首先要按字典序最小的方式输出,所以自然输入后要对这些字母进行排列,然后就是输入了,用scanf不能读空格,所以怎么建图呢??设置一个变量判断读入的先后顺序,那么建图完毕后,就拓扑排序了,那么多种方式自然就是dfs回溯了..那么这个问题就得到了解决.. 题目: Following Orders Time Limit:

ACM/ICPC 之 拓扑排序+DFS(POJ1128(ZOJ1083))

经典的拓扑排序问题,难点在于字典序输出和建立拓扑图,另外理解题意是最难的难点,没有之一... POJ1128(ZOJ1083)-Frame Stacking 题意:每个图片由同一字母组成的边框表示,每个图片的字母都不同: 在一个最多30*30的区域放置这些图片,问底层向顶层叠加的图片次序,多选时按字典序输出 注:每个图片的四边都会有字符显示,其中顶点显示两边. 题解:题意的理解是难点,题目对图片的范围确定说得有点含糊不清,博主一开始就被出现的五张图片的样例迷惑,理解重心放错了.题目最需要理解的是

HDU 5438 拓扑排序+DFS

Ponds Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 3234    Accepted Submission(s): 997 Problem Description Betty owns a lot of ponds, some of them are connected with other ponds by pipes, a

Codeforces Round #292 (Div. 2) D. Drazil and Tiles [拓扑排序 dfs]

传送门 D. Drazil and Tiles time limit per test 2 seconds memory limit per test 256 megabytes Drazil created a following problem about putting 1 × 2 tiles into an n × m grid: "There is a grid with some cells that are empty and some cells that are occupie

HDU 5438 Ponds (拓扑排序+DFS)2015 ACM/ICPC Asia Regional Changchun Online

[题目链接]:click here~~ [题目大意]: 题意:在一个无向图中有 p 个点, m 条边,每个点有一个值 vi .不断的删去度数小于2的点直到不能删为止.求新图中所有点个数为奇数的连通分量的点值的和. 1<p<10^4,1<m<10^5 [思路]删边考虑类似拓扑排序的写法,不过topsort是循环一遍1到n结点入度为0的结点,然后加入到队列中,这里只要改一下度数小于等于1,最后DFS 判断一下 挫挫的代码: /* * Problem: HDU No.5438 * Run

拓扑排序/DFS HDOJ 4324 Triangle LOVE

题目传送门 题意:判三角恋(三元环).如果A喜欢B,那么B一定不喜欢A,任意两人一定有关系连接 分析:正解应该是拓扑排序判环,如果有环,一定是三元环,证明. DFS:从任意一点开始搜索,搜索过的点标记,否则超时.看是否存在两点路程只差等于2,如果存在,则说明有上述的三角环.其他做法. 收获:DFS搜索一定要用vis数组啊,否则很容易超时的 代码(拓扑排序): /************************************************ * Author :Running_T

HDU3342有向图判圈DFS&amp;&amp;拓扑排序法

HDU3342 Legal or Not 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3342 题目意思:一群大牛互相问问题,大牛有不会的,会被更厉害的大牛解答,更厉害的大牛是会的东西比大牛多,但是有的时候更厉害的大牛会装弱,出来问问题,这样就被大牛解答了.这样就形成了一个圈.题目的意思就是让你在一个有向图里面判断是否存在环.我们可以通过dfs和拓扑排序两种方法. DFS的代码: //Author: xiaowuga #include <bits

UVA10305 Ordering Tasks【DFS】【拓扑排序】

Ordering Tasks Input: standard input Output: standard output Time Limit: 1 second Memory Limit: 32 MB John has n tasks to do. Unfortunately, the tasks are not independent and the execution of one task is only possible if other tasks have already been

【DFS】【拓扑排序】【动态规划】Gym - 100642A - Babs&#39; Box Boutique

给你10个箱子,有长宽高,每个箱子你可以决定哪个面朝上摆.把它们摞在一起,边必须平行,上面的不能突出来,问你最多摆几个箱子. 3^10枚举箱子用哪个面.然后按长为第一关键字,宽为第二关键字,从大到小排序. 如果前面的宽大于等于后面的宽,就连接一条边. 形成一张DAG,拓扑排序后跑最长路即可. #include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespa