如何求拓撲排序的所有種類及種類數


輸入:第一行為點數n和各連接邊數m

   接下來m行寫某一條有向邊的起始點和終止點

 

輸出:拓撲排序所有方案和方案種數

 

sample input

9 10
0 1
1 3
2 4
3 2
3 6
5 4
6 5
7 5
8 6
8 7

sample output

0 1 3 2 8 6 7 5 4
0 1 3 2 8 7 6 5 4
0 1 3 8 2 6 7 5 4
0 1 3 8 2 7 6 5 4
0 1 3 8 6 2 7 5 4
0 1 3 8 6 7 2 5 4
0 1 3 8 6 7 5 2 4
0 1 3 8 7 2 6 5 4
0 1 3 8 7 6 2 5 4
0 1 3 8 7 6 5 2 4
0 1 8 3 2 6 7 5 4
0 1 8 3 2 7 6 5 4
0 1 8 3 6 2 7 5 4
0 1 8 3 6 7 2 5 4
0 1 8 3 6 7 5 2 4
0 1 8 3 7 2 6 5 4
0 1 8 3 7 6 2 5 4
0 1 8 3 7 6 5 2 4
0 1 8 7 3 2 6 5 4
0 1 8 7 3 6 2 5 4
0 1 8 7 3 6 5 2 4
0 8 1 3 2 6 7 5 4
0 8 1 3 2 7 6 5 4
0 8 1 3 6 2 7 5 4
0 8 1 3 6 7 2 5 4
0 8 1 3 6 7 5 2 4
0 8 1 3 7 2 6 5 4
0 8 1 3 7 6 2 5 4
0 8 1 3 7 6 5 2 4
0 8 1 7 3 2 6 5 4
0 8 1 7 3 6 2 5 4
0 8 1 7 3 6 5 2 4
0 8 7 1 3 2 6 5 4
0 8 7 1 3 6 2 5 4
0 8 7 1 3 6 5 2 4
8 0 1 3 2 6 7 5 4
8 0 1 3 2 7 6 5 4
8 0 1 3 6 2 7 5 4
8 0 1 3 6 7 2 5 4
8 0 1 3 6 7 5 2 4
8 0 1 3 7 2 6 5 4
8 0 1 3 7 6 2 5 4
8 0 1 3 7 6 5 2 4
8 0 1 7 3 2 6 5 4
8 0 1 7 3 6 2 5 4
8 0 1 7 3 6 5 2 4
8 0 7 1 3 2 6 5 4
8 0 7 1 3 6 2 5 4
8 0 7 1 3 6 5 2 4
8 7 0 1 3 2 6 5 4
8 7 0 1 3 6 2 5 4
8 7 0 1 3 6 5 2 4
sum:52

 

代碼:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 int n,m;
 6 int s[100][100];        //鄰接矩陣,用於保存圖的結構 
 7 int visit[100];        //頂點標志 
 8 int indegree[100];        //各個頂點的入度 
 9 int ans[100];
10 int sum=0;            //記錄拓撲排序總數 
11 void DFS(int num)        //num記錄當前已經訪問的頂點個數 
12 {
13     int i,j,k;
14     if (num==n){        //訪問完n個頂點代表這是一條新的可走的拓撲路徑 
15         sum++;             //路徑總數加1 
16         for (i=0;i<n;i++)
17             printf("%d ",ans[i]);
18         printf("\n");
19         return;
20     } 
21     
22     for (i=0;i<n;i++){
23         if ((!indegree[i])&&(!visit[i])){        //如果頂點i入度為0且沒有被訪問過 
24             for (j=0;j<n;j++){
25                 if (s[i][j])    indegree[j]--;    //遍歷所有和它連接的點並且斷開聯系(即點的入度減1) 
26             }
27             
28             visit[i]=1;            //該入度為0的點標記訪問過 
29             ans[num]=i;            //儲存值 
30             DFS(num+1);            //以訪問點數+1 
31             
32             for (k=0;k<n;k++){    //回溯,恢復現場,將入度重新加一,並且將該頂點標記為未訪問
33                 if (s[i][k])    indegree[k]++;
34             }
35             visit[i]=0;            //回溯標志 方便下一次for循環使用 
36                                 //ans沒有必要回溯,因為后續的值可以直接覆蓋 
37         }
38     }
39     return;
40 }
41  
42 int main(){
43     int a,b,i,j,num;
44     scanf("%d%d",&n,&m);
45     memset(indegree,0,sizeof(indegree));
46     memset(s,0,sizeof(s));
47     memset(visit,0,sizeof(visit));
48     memset(ans,0,sizeof(ans));
49     
50     for (i=1;i<=m;i++){
51          scanf("%d%d",&a,&b);
52         s[a][b]=1;
53         indegree[b]++;
54      } 
55  
56     DFS(0);
57     cout<<"sum:"<<sum;
58     return  0;
59 } 

 


免責聲明!

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



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