POJ 1094 Sorting It All Out
阿新 • • 發佈:2020-08-18
題目連結: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 }View Code
Tips:
關於拓撲排序,一般用刪邊法,即找到一個入度為0的點並輸出,然後刪掉這個點,並且同時刪掉跟它相連的邊,然後重複上述步驟。這個方法也可以用來判斷圖中是否存在迴路。(判斷圖是否連通用dfs)