升级版不用栈,用递归来列举出所有的拓扑序列,循环内嵌套递归的思想值得好好领悟!
例题:
若干士兵站队,已知一些约束的关系,比如A必须站在B前面,B必须站在F前面等。求所有可能的站队方式
输入:所有的约束关系,比如AB(表示A必须站在B前面)HJ
输出:列出所有的站队方式
测试用例:
代码:
1 #include <stdio.h> 2 #include <string.h> 3 4 #define MAX_VERTEX_NUM 100 5 6 int ver_num; 7 int indeg[MAX_VERTEX_NUM]; 8 int help[MAX_VERTEX_NUM]; 9 int graph[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; 10 char vertex[MAX_VERTEX_NUM]; 11 12 void CreateMGragh() 13 { 14 int i,j; 15 int n1,n2,f1,f2; 16 char ch1,ch2,ch3; 17 while(1){ 18 scanf("%c%c%c",&ch1,&ch2,&ch3); 19 f1 = f2 = 0; 20 for (i=0; vertex[i] != 0; i++){ 21 if (vertex[i] == ch1){ 22 f1 = 1; 23 n1 = i; 24 break; 25 } 26 } 27 if (f1 == 0){ 28 vertex[i] = ch1; 29 n1 = i; 30 } 31 for (j=0; vertex[j] != 0; j++){ 32 if (vertex[j] == ch2){ 33 f2 = 1; 34 n2 = j; 35 break; 36 } 37 } 38 if (f2 == 0){ 39 vertex[j] = ch2; 40 n2 = j; 41 } 42 43 graph[n1][n2] = 1; 44 indeg[n2]++; 45 46 if (ch3 == ' '){ 47 break; 48 } 49 } 50 for (i=0; vertex[i] != 0; i++); 51 ver_num = i; 52 } 53 54 int topsort(int cnt) 55 { 56 int i,j; 57 int backup[MAX_VERTEX_NUM]; 58 59 if (cnt == ver_num){ 60 for (i=0; i<ver_num; i++){ 61 printf("%c",vertex[help[i]]); 62 } 63 printf(" "); 64 return 1; 65 } 66 67 for (i=0; i<ver_num; i++){ // indeg数组递归时发生变化,因此备份 68 backup[i] = indeg[i]; 69 } 70 for (i=0; i<ver_num; i++){ // 循环内嵌套递归的思想好好领悟一下 71 if (indeg[i] == 0){ // 入度为0 72 help[cnt] = i; // 将cnt与下标巧妙关联 73 indeg[i] = -1; 74 for (j=0; j<ver_num; j++){ // 所有与i点连接的点的入度都-1 75 if (graph[i][j] == 1){ 76 indeg[j]--; 77 } 78 } 79 if (topsort(cnt+1) == 0){ // 递归下去 80 return 0; 81 } 82 for (j=0; j<ver_num; j++){ // 还原indeg数组 83 indeg[j] = backup[j]; 84 } 85 } 86 } 87 return 1; 88 } 89 90 int main() 91 { 92 CreateMGragh(); 93 topsort(0); 94 return 0; 95 }
测试结果: