算法總結之拓撲排序


拓撲排序

1.一般應用

      拓撲排序常用來確定一個依賴關系集中,事物發生的順序。例如,在日常工作中,可能會將項目拆分成A、B、C、D四個子部分來完成,但A依賴於B和D,C依賴於D。為了計算這個項目進行的順序,可對這個關系集進行拓撲排序,得出一個線性的序列,則排在前面的任務就是需要先完成的任務。

2.實現的基本方法

  (1)從有向圖中選擇一個沒有前驅(即入度為0)的頂點並且輸出它.

  (2)從網中刪去該頂點,並且刪去從該頂點發出的全部有向邊.

  (3)重復上述兩步,直到剩余的網中不再存在沒有前趨的頂點為止.

3.C++版本實現

 1 /*以鄰接矩陣Edge[A][B]=N存放圖信息:A指向B,權值為N*/
 2 /*假設不相連的邊的Edge==INT_MAX*/
 3 void Topo()
 4 {
 5     sort(Edge+1,Edge+N+1);
 6     for (int i=1; i<=N; i++)
 7     {
 8         int j;
 9         for (j=1; j<=N; i++)  //vis為標記數組,標記是否已經存在在Topo數組中
10             if (!vis[j]&&!in[j]) //in數組表示的下標頂點的入度
11             {
12                 Topo[i]=j;
13                 vis[j]=1;
14                 break;
15             }
16         for (int k=1;k<=N;k++) //將與j點相連的頂點的入度刷新
17             if (Edge[j][k]!=INT_MAX)
18                 in[k]--;
19     }
20 }

4.反向建圖

  拓撲排序並不一定唯一,有時會要求頂點數值大的盡量在前,這個時候應該反向建圖,再進行拓撲排序,來保證更多小數值頂點在后面。(貪心思想?)

  Eg:HDU 4857 POJ 3687(反向建圖+拓撲排序)

5.優化

  拓撲排序每次選擇一個頂點進入序列后,要更新所有與這個頂點相連的頂點的入度。而上面的代碼全是把所有的頂點都遍歷了一邊。

  這里可以使用鄰接表或者鏈式前向星這一類數據結構,來記錄圖的信息,可以做到只遍歷與該頂點相連的頂點

6.優先隊列實現

 1 /*優先隊列+鄰接表實現拓撲排序*/
 2 void Topo()
 3 {
 4     priority_queue<int> que;
 5     for (int i=1; i<=N; i++) //將入度為零的頂點壓入隊列
 6         if (dis[i]==0)
 7             que.push(i);
 8     int p=N+1;
 9     while (!que.empty())
10     {
11         int tmp=que.top();
12         que.pop();
13         topo[--p]=tmp;     //存入topo數組
14         int z=first[tmp];
15         while (z!=-1)       //鄰接表遍歷與tmp相連的頂點
16         {
17             dis[end[z]]--; //入度減一
18             if(!dis[end[z]]) que.push(end[z]);
19             z=next[z];
20         }
21     }
22 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM