POJ 1094 Sorting It All Out
题目链接:POJ 1094
| Describe: |
| An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from smallest to largest. For example, the sorted sequence A, B, C, D implies that A < B, B < C and C < D. in this problem, we will give you a set of relations of the form A < B and ask you to determine whether a sorted order has been specified or not. |
| Input: |
| Input consists of multiple problem instances. Each instance starts with a line containing two positive integers n and m. the first value indicated the number of objects to sort, where 2 <= n <= 26. The objects to be sorted will be the first n characters of the uppercase alphabet. The second value m indicates the number of relations of the form A < B which will be given in this problem instance. Next will be m lines, each containing one such relation consisting of three characters: an uppercase letter, the character "<" and a second uppercase letter. No letter will be outside the range of the first n letters of the alphabet. Values of n = m = 0 indicate end of input. |
| Output: |
| For each problem instance, output consists of one line. This line should be one of the following three: Sorted sequence determined after xxx relations: yyy...y. Sorted sequence cannot be determined. Inconsistency found after xxx relations. where xxx is the number of relations processed at the time either a sorted sequence is determined or an inconsistency is found, whichever comes first, and yyy...y is the sorted, ascending sequence. |
| Sample Input: |
| 4 6 A<B A<C B<C C<D B<D A<B 3 2 A<B B<A 26 1 A<Z 0 0 |
| Sample Output: |
| Sorted sequence determined after 4 relations: ABCD. Inconsistency found after 2 relations. Sorted sequence cannot be determined. |
题目大意:
给n个连续的字母,m个判断语句,问在得到多少语句之后可以判断出这些字母构成一个环,或者一个排序,亦或者不能确定。
解题思路:
每次读入一组数据,就拓扑排序判断一下,具体见代码的详细注释。根据题意和输入输出,会发现此题跟图有关,从而想到最终的排序用拓扑排序。
此题也附上快150行的的一次写的错误代码,想的太复杂了。
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 // arr用来存储图,in用来存储入度,ans用来存储排好序的序列 6 int arr[26][26],in[26],ans[26]; 7 void init(int n) // 初始化函数 8 { 9 for(int i = 0; i < n; i++) 10 for(int j = 0; j < n; j++) 11 arr[i][j] = 0; 12 for(int i = 0; i < n; i++) 13 in[i] = 0; 14 } 15 int topo(int n) 16 { 17 int tmp[26],t,f = 1,cont = 0; 18 for(int i = 0; i < n; i++) tmp[i] = in[i]; // 临时数组复制入度数组,防止入度数组改变 19 for(int i = 0; i < n; i++) 20 { 21 cont = 0; // 表示入度为0的个数 22 t = -1; // 存储入度为0的序号 23 for(int j = 0; j < n; j++) // 循环寻找入度为0的 24 { 25 if(tmp[j] == 0) 26 { 27 cont++; 28 t = j; 29 } 30 } 31 if(cont > 1) f = 0; // 如果入度为零的数目大于1,说明暂时不能确定,但是不能直接return 32 // 因为可能还存在成环的情况我们没有检测出来,所以先记录下来 33 if(cont == 0) return 2; // 如果没有一个入度为0的,说明成环了 34 ans[i] = t; // 记录到答案数组 35 tmp[t] = -1; // 注意,不能忘记这一步,表示该点已经搜索到过了,不能重复搜索 36 for(int j = 0; j < n; j++) // 相连的点入度都减一 37 if(arr[t][j] == 1) 38 tmp[j]--; 39 } 40 return f; 41 } 42 int main() 43 { 44 int n,m,x,y,f,cnt,t; // n,m,a,b,c为题目变量,f为标志,cnt为计数器,t为中间变量 45 char a,b,c; 46 while(~scanf("%d%d",&n,&m) && n+m) 47 { 48 cnt = 0; // 各种初始化 49 f = 1; 50 init(n); 51 while(m--) 52 { 53 scanf("\n%c%c%c",&a,&b,&c); 54 if(f == 1) 55 { 56 x = a-'A'; // 数据类型转换 57 y = c-'A'; 58 arr[x][y] = 1; // 有向图添加一条边 59 in[y]++; // 入度加一 60 cnt++; 61 t = topo(n); // 进行一次判断 62 if(t == 1) // 如果能排序 63 { 64 printf("Sorted sequence determined after %d relations: ",cnt); 65 for(int i = 0; i < n; i++) printf("%c",ans[i]+'A'); 66 printf(".\n"); 67 f = 0; 68 } else if(t == 2) { // 如果成环 69 printf("Inconsistency found after %d relations.\n",cnt); 70 f = 0; 71 } 72 } 73 } // 如果最终都没确定,则无法确定 74 if(f == 1) printf("Sorted sequence cannot be determined.\n"); 75 } 76 return 0; 77 }
错误代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 struct node 7 { 8 int time,id,ex; 9 node *next; 10 } arr[26]; 11 int n,m,flag,cnt,f[26],d[26],bp[26]; 12 void backup(int n) 13 { 14 for(int i = 0; i < n; i++) 15 bp[i] = arr[i].time; 16 } 17 void recover(int n) 18 { 19 for(int i = 0; i < n; i++) 20 arr[i].time = bp[i]; 21 memset(bp,0,sizeof(bp)); 22 } 23 void init(int n) 24 { 25 for(int i = 0; i < n; i++) 26 { 27 arr[i].id = i; 28 arr[i].ex = 0; 29 arr[i].time = 0; 30 arr[i].next = NULL; 31 } 32 for(int i = 0; i < n; i++) 33 f[i] = 0; 34 } 35 int num(int n) 36 { 37 for(int i = 0; i < n; i++) 38 { 39 if(arr[i].time == 0 && f[i] == 0 && arr[i].ex == 1) 40 { 41 return i; 42 } 43 } 44 return -1; 45 } 46 bool check(int n) 47 { 48 backup(n); 49 int t; 50 while(true) 51 { 52 t = num(n); 53 if(t == -1) break; 54 f[t] = 1; 55 node *tmp = arr[t].next; 56 while(tmp != NULL) {arr[tmp->id].time--;tmp = tmp->next;} 57 } 58 for(int i = 0; i < n; i++) 59 { 60 if(f[i] == 0 && arr[i].ex == 1) 61 return false; 62 } 63 return true; 64 } 65 bool istopo(int n) 66 { 67 for(int i = 0; i < n; i++) 68 if(arr[i].ex == 0) 69 return false; 70 return true; 71 } 72 void topo(int n) 73 { 74 int t; 75 while(true) 76 { 77 t = num(n); 78 if(t == -1) break; 79 f[t] = 1; 80 node *tmp = arr[t].next; 81 while(tmp != NULL) {arr[tmp->id].time--; tmp = tmp->next;} 82 printf("%c",t+'A'); 83 } 84 } 85 void dfs(int t) 86 { 87 d[t] = 1; 88 node *tmp = arr[t].next; 89 while(tmp != NULL) 90 { 91 dfs(tmp->id); 92 tmp = tmp->next; 93 } 94 } 95 int main() 96 { 97 while(~scanf("%d%d",&n,&m) && n+m) 98 { 99 memset(d,0,sizeof(d)); 100 memset(f,0,sizeof(f)); 101 flag = -1; //-1表示正常,-2表示不能拓扑,-3表示可以拓扑 102 cnt = 0; 103 init(n); 104 int x,y; 105 char a,b,c; 106 while(m--) 107 { 108 scanf("\n%c%c%c",&a,&b,&c); 109 if(flag == -1) 110 { 111 x = a-'A'; 112 y = c-'A'; 113 node *tmp = (node*)malloc(sizeof(node)); 114 node *temp = &arr[x]; 115 while(temp->next != NULL) temp = temp->next; 116 tmp->id = y; 117 tmp->next = NULL; 118 temp->next = tmp; 119 arr[x].ex = 1; 120 arr[y].ex = 1; 121 arr[y].time++; 122 cnt++; 123 if(!check(n)) flag = -2; 124 recover(n); 125 memset(f,0,sizeof(f)); 126 if(istopo(n) && flag == -1) flag = -3; 127 } 128 } 129 if(flag == -2) printf("Inconsistency found after %d relations.\n",cnt); 130 else if(flag == -3) { 131 printf("Sorted sequence determined after %d relations: ",cnt); 132 topo(n); 133 printf(".\n"); 134 } else if(flag == -1) { 135 dfs(num(n)); 136 int ff = 1; 137 for(int i = 0; i < n; i++) 138 if(d[i] == 0) 139 ff = 0; 140 if(ff == 0) printf("Sorted sequence cannot be determined.\n"); 141 else { 142 printf("Sorted sequence determined after %d relations: ",cnt); 143 topo(n); 144 printf(".\n"); 145 } 146 } 147 } 148 return 0; 149 }
Tips:
关于拓扑排序,一般用删边法,即找到一个入度为0的点并输出,然后删掉这个点,并且同时删掉跟它相连的边,然后重复上述步骤。这个方法也可以用来判断图中是否存在回路。(判断图是否连通用dfs)

浙公网安备 33010602011771号