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 }
View Code

 

 

 

Tips:

关于拓扑排序,一般用删边法,即找到一个入度为0的点并输出,然后删掉这个点,并且同时删掉跟它相连的边,然后重复上述步骤。这个方法也可以用来判断图中是否存在回路。(判断图是否连通用dfs)

 

posted @ 2020-08-18 11:14  不敢说的梦  阅读(107)  评论(0)    收藏  举报