1. 程式人生 > >拓撲排序+有向無環圖(DAG)的檢測

拓撲排序+有向無環圖(DAG)的檢測

參考: 演算法導論第三版 p356, 資料結構與演算法分析p218, 演算法入門經典p110

拓撲排序的兩張方法:

1.dfs搜尋
2.模擬人工的拓撲
兩種方法的效率都是O(V + E)

$$拓撲排序的方法也是有向無環圖檢測的方法

/*
拓撲排序 dfs搜尋 - 鄰接表
可以判斷一個圖是否有環
*/

#include <cstdio>
#include <vector>
#include <stack>
using std::vector;
using std::stack;


const int MAXN = 10;
const int INIT = 0;
const int GRAY = 1; //參考演算法導論的染色, GRAY表示一條後向邊
const int BLACK = 2;

int visit[MAXN];
int time = 0;
vector<vector<int>>g(MAXN);
stack<int> ans;

bool dfs(int p) // recursion遞迴
{
    visit[p] = GRAY; //表示正被訪問(正在訪問它或者它的子孫)的結點
    for (int i = 0; i < g[p].size(); ++i)
    {
        int temp = g[p][i];
        if (visit[temp] == INIT)
        {
            if (dfs(temp) == false)
                return false;
        }
        else if (visit[temp] == GRAY)
        {
		    //GRAY表示一條後向邊,代表子孫指向祖先,這條邊說明有環
            return false; // 有環, 不是DAG(有向無環圖)
        }
    }
    visit[p] = BLACK; //已經被訪問過(或者已經排序好了)
    ans.push(p);
}


bool toposort(int N) // 拓撲排序 topological sort O(E + V)
{
    for (int i = 1; i <= N; ++i) // 初始化
    {
        visit[i] = INIT;
    }
    time = 0;
    for (int i = 1; i <= N; ++i) // 圖可能不是連通的
    {
        if (visit[i] == INIT)
        {
            if (dfs(i) == false) // 遞迴呼叫dfs
                return false;
        }
    }
    return true;
}

void print()
{
    while (!ans.empty())
    {
        printf("%d\n", ans.top());
        ans.pop();
    }
}

int  main()
{
	freopen("F://input.txt", "r", stdin);
	int N, v, t;
	scanf("%d", &N);
	while (scanf("%d%d", &v, &t) != EOF)
	{
		g[v].push_back(t);//構造鄰接表
	}
    if (toposort(N))
        print();
    else
        printf("The graph is not a DAG\n");
}


/*
拓撲排序-模擬人工的方法-鄰接表
和dfs的拓撲排序一樣,這個方法也可以判斷一個圖是否有環
第一種沒有優化, 第二種使用了佇列優化
*/

#include <cstdio>
#include <vector>
#include <queue>
using std::vector;
using std::queue;

const int MAXN = 10;

vector<vector<int>>g(MAXN);
queue<int>  ans; // 出隊順序儲存在ans佇列裡面, 也可以保持在陣列中
int  indegree[MAXN];




bool toposort_1(int N)//沒有優化,尋找度為0的點每次掃描一遍陣列 O(V*V)
{
    bool flag = true;
    while (flag)
    {
        flag = false;
        for (int i = 1; i <= N; ++i)
        {
            if (indegree[i] == 0)
            {
                indegree[i] = -1;// 結點i已經被排序
                ans.push(i);
                flag = true;
                for (int j = 0; j < g[i].size(); ++j)
                {
                    int temp = g[i][j];
                    --indegree[temp];
                }
            }
        }
    }
    if (ans.size() < N)
        return false;
    return true;
}

bool toposort(int N)//佇列優化, 從佇列中找出度為0的結點 O(V + E)
{
    queue<int> que;
    for (int i = 1; i <= N; ++i)
    {
        if (indegree[i] == 0)
            que.push(i);
    }
    while (!que.empty())
    {
        int p = que.front();
        ans.push(p);
        que.pop();
        for (int i = 0; i < g[p].size(); ++i)
        {
            int temp = g[p][i];
            if (--indegree[temp] == 0)//度為0的結點肯定產生在減小入度的地方
                que.push(temp);
        }
    }
    if (ans.size() < N)//如果已經排序的少於總結點數,說明圖有環
        return false;
    return true;
}
void print()
{
    while (!ans.empty())
    {
        printf("%d\n", ans.front());
        ans.pop();
    }
}

int  main()
{
	freopen("F://input.txt", "r", stdin);
	int N, v, t;
	scanf("%d", &N);
	while (scanf("%d%d", &v, &t) != EOF)
	{
		g[v].push_back(t);//構造鄰接表
        ++indegree[t]; // t的入度+1
	}
    if (toposort(N))
        print();
    else
        printf("The graph is not a DAG\n");
}

/*
測試資料: <<資料結構與演算法分析>> p218 9-4圖
7
1 2
1 3
1 4
2 4
2 5
5 4
5 7
7 6
4 3
4 7
4 6
3 6
*/


相關推薦

排序+(DAG)的檢測

參考: 演算法導論第三版 p356, 資料結構與演算法分析p218, 演算法入門經典p110 拓撲排序的兩張方法: 1.dfs搜尋 2.模擬人工的拓撲 兩種方法的效率都是O(V + E)$$拓撲排序的方法也是有向無環圖檢測的方法 /* 拓撲排序 dfs搜尋 - 鄰接表 可

DAG 排序 程式碼解釋

目錄: DAG定義 舉例描述 實際運用 演算法描述 演算法實戰 演算法視覺化 定義 在圖論中,由一個有向無環圖的頂點組成的序列,當且僅當滿足下列條件時,稱為該圖的一個拓撲排序(英語:Topological sorting)。 每個頂點出現且只出現一

演算法: (DAG)的排序

更新: 拓撲排序有2中方法(最後結果可能不同,因為拓撲排序有多解)。 一個簡單的求拓撲排序的演算法是先找出任意一個沒有入邊的頂點,然後將它和它的邊從圖中刪除。然後對剩餘部分使用同樣的操作。 public ArrayList<Integer&g

C#實現(DAG)排序

對一個有向無環圖(Directed Acyclic Graph簡稱DAG)G進行拓撲排序,是將G中所有頂點排成一個線性序列,使得圖中任意一對頂點u和v,若邊(u,v)∈E(G),則u線上性序列中出現在v之前。通常,這樣的線性序列稱為滿足拓撲次序(Topological Order)的序列,簡稱拓撲序列。簡單的

(DAG)的所有序列

如果index>length(S(i)),即index的值如果大於集合S(i)的大小了,說明當前集合S(i)中的值都用過了,必須回溯到前一個序列元素result[i-1],將它的值變成它對應集合(S(i-1))中的下一個可能的值.假設之前result[i-1]使用的是S(i-1)[n],那麼現在resu

SparkDAG圖解與演示

目錄:1、有向無環圖 2、程式碼結構 3、程式碼學習步鄹及方法 4、重點程式碼講解 5、程式碼展現 6、執行結果 ——————————————————————————————————— 1、有向無環圖 在圖論中,如果一個有向圖無法從某個頂點出發經過若干條邊回到該點,則這個

Spark的DAG(程式碼及圖解)

目錄: 1、有向無環圖 2、程式碼結構 3、程式碼學習步鄹及方法 4、重點程式碼講解 5、程式碼展現 6、執行結果 ——————————————————————————————————— 1、有向無環圖 在圖論中

->->排序

文字描述   關於有向無環圖的基礎定義:     一個無環的有向圖稱為有向無環圖,簡稱DAG圖(directed acycline graph)。DAG圖是一類較有向樹更一般的特殊有向圖。        舉個例子說明有向無環圖的應用。假如有一個表示式: ((a+b)*(b*(c+d))+(c+d)*e

排序(判斷是否是

要進行拓撲排序之前,該圖要是有向無環圖。 排序方法: 1、從有向圖中選取一個沒有前驅的頂點,並輸出之 ;2、從有向圖中刪去此頂點以及所有以它為尾的弧; 3、重複上述兩步,直至圖空,或者圖不空但找不到無前驅的頂點為止。 #include<stdio.h>

論】排序

1. 引言 有向無環圖(Directed Acyclic Graph, DAG)是有向圖的一種,字面意思的理解就是圖中沒有環。常常被用來表示事件之間的驅動依賴關係,管理任務之間的排程。拓撲排序是對DAG的頂點進行排序,使得對每一條有向邊(u, v),均有u(在排序記錄中)比v先出現。亦可理解為對某點v而言,只

Java實現排序:基於鄰接矩陣,針對

public void topoSort(){//僅僅針對有向圖,基本思路是找到一個無後繼的結點,將其刪除,並放到排序陣列的尾端,依次迴圈。直到沒有結點。 int originalVertex

排序

拓撲排序只能用於無環圖。// 頂點class Vertex3 {    char label;    boolean visited;    public Vertex3(char label) {        this.label = label;        visi

最短路模板(二)——用排序解決中的最短路

測試資料: 8 13 5 4 0.35 4 7 0.37 5 7 0.28 5 1 0.32 4 0 0.38 0 2 0.26 3 7 0.39 1 3 0.29 7 2 0.34 6 2 0.40 3 6 0.52 6 0 0.58 6 4 0.93 測試結果: 5

排序(DFS實現)

1.有向無環圖的拓撲排序 // enDegree表示每個頂點的入度,這個資料結構可以從圖的結構求出來 // graph是一個二維陣列,但是這個陣列不是圖的鄰接矩陣,graph[i][j]表示依賴於i的第

算法87-----DAG排序

gree 方案 跳過 分享圖片 分享 return tail take != 一、題目:課程排表---210 課程表上有一些課,是必須有修學分的先後順序的,必須要求在上完某些課的情況下才能上下一門。問是否有方案修完所有的課程?如果有的話請返回其中一個符合要求的路徑,否則返

建立的鄰接表,深度優先遍歷和廣度優先遍歷的遞迴與非遞迴演算法,判斷是否是,並輸出一種序列

/*(1)輸入一組頂點,建立有向圖的鄰接表,進行DFS(深度優先遍歷)和BFS(廣度優先遍歷)。 寫出深度優先遍歷的遞迴和非遞迴演算法。 (2)根據建立的有向圖,判斷該圖是否是有向無環圖,若是,則輸出其一種拓撲有序序列。*/ #include<stdio.h>

HDU 3249 Test for job (上的最長路,DP)

code head struct sin == cout article scanf for ?? 解題思路: 求有向無環圖上的最長路。簡單的動態規劃#include <iostream> #include <cstring> #include

HOJ 13845 Atomic Computer的動態規劃

-1 會有 bsp pre 但是 自帶 += 排列組合 開始 考慮任意一個數字,任何一個都會有奇怪的。。性質,就是一個可以保證不重復的方案——直接簡單粗暴的最高位加數字。。於是,如同上面的那個題:+1、-1、0 但是考慮到65536KB的標準內存限制,會得出一個奇怪的性質,

CSU 1804 - - [樹形DP]

其中 如果 init max 枚舉 time 包含 mod %d 題目鏈接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 Bobo 有一個 n 個點,m 條邊的有向無環圖(即對於任意點 v,不存在從點 v 開

c/c++ directed acycline graph

rect 如果 拓撲排序 type 第一個 ima 結構 alt lse c/c++ 有向無環圖 directed acycline graph 概念: 圖中點與點之間的線是有方向的,圖中不存在環。用鄰接表的方式,實現的圖。 名詞: 頂點的入度:到這個頂點的線的數量。 頂