1. 程式人生 > >UVA10305:拓撲排序

UVA10305:拓撲排序

其中 限定 back 所有結點 using nes cto span 同時

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 executed.

John有n件工作要做,不幸的是這些工作並不獨立,而是某件工作需要在另一件已經執行完了以後才能執行。


Input
The input will consist of several instances of the problem. Each instance begins with a line containing two integers, 1 ≤ n ≤ 100 and m. n is the number of tasks (numbered from 1 to n) and m is the number of direct precedence relations between tasks. After this, there will be m lines with two integers i and j, representing the fact that task i must be executed before task j. An instance with n = m = 0 will ?nish the input.

輸入會包括若幹組。每組先輸入 n([1,100])和 m,其中 n 代表標號為 1~n 的 n 件工作。接下來的 m 行給出工作之間的優先度,每行給出兩個整數 i、j,代表 i 會在 j 之前執行,n = m = 0時結束輸入。


Output
For each instance, print a line with n integers representing the tasks in a possible order of execution.

對於每組數據,打印n個整數,代表著一種可能出現的執行順序(意即多解輸出某一解即可)。


Sample Input
5 4

1 2

2 3

1 3

1 5

0 0
Sample Output
1 4 2 5 3

介紹:

把每個變量看成一個點,“小於”關系看成有向邊(比如輸入1 2,我們可以畫箭頭1-->2),這樣就可以把數據轉化為一個有向圖。把圖的所有結點排序使得每一條有向邊(u,v)對應的u都排在v的前邊(不一定相鄰)。在圖論中,這個問題稱為拓撲排序。

本題思路:

顯然,我們無法從前到後去貪心選取路徑,比如用樣例來講,如果我們先搜索到了 1->3 這條路,然後就儲存在結果上的話,無法得知是否還有 1->2->3 這個限定路徑,之後再搜到 2 這個點也沒法往裏補,而 5 這個點處在哪裏也不好寫命令。

所以反過來貪心:可以發現當深搜到最底端到達點 3 時,它後面再也沒有點了,那麽無論如何處置其他的點,3放在最後總是沒錯的。而為了得出點 1 和點 2 的順序,可以在某個點for遍歷了它的全部出度並深搜以後,再將此點放入拓撲序的前端。比如點 1 先掃描到了點 3,到頭了,3放裏;然後點 1 還有個指向點 2 的箭頭,再dfs點 2,於是點 2 也放裏了;然後點 1 遍歷結束,點 1 放裏……請用代碼細細體會。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <vector>
 6 using namespace std;
 7 
 8 const int maxn = 105;
 9 int n, m;
10 int topo[maxn], temp;//最終的拓撲序
11 bool book[maxn];//記錄是否已經訪問過某點
12 vector <int> chu[maxn];//chu[i]儲存i指向的所有點
13 
14 void dfs(int cur)
15 {
16     for (int i : chu[cur])
17     //C++11的特性,表示遍歷了vector(實際上哪個容器都可以這麽用),i代表具體元素值而不是位置
18         if (!book[i])    dfs(i);
19     book[cur] = true;
20     topo[temp--] = cur;
21 }
22 
23 int main()
24 {
25     while (~scanf("%d%d", &n, &m) && (n | m))//註意m是可以等於0的,n、m同時等於0才終止
26     {
27         //輸入和預處理
28         for (int i = 0; i < m; i++)
29         {
30             int a, b;
31             scanf("%d%d", &a, &b);
32             chu[a].push_back(b);//把b作為a的出度
33         }
34         //深搜
35         memset(book, false, sizeof(book));
36         temp = n;
37         for (int i = 1; i <= n; i++)
38             if (!book[i])    dfs(i);
39         //輸出
40         for (int i = 1; i <= n; i++)    
41             chu[i].clear(), printf("%d%c", topo[i], " \n"[i==n]);
42     }
43 }

UVA10305:拓撲排序