POJ- 1094 Sorting It All Out---拓撲排序是否唯一的判斷


題目鏈接:

https://vjudge.net/problem/POJ-1094

題目大意:

該題題意明確,就是給定一組字母的大小關系判斷他們是否能組成唯一的拓撲序列。是典型的拓撲排序,但輸出格式上確有三種形式:

   1.該字母序列有序,並依次輸出;

   2.該序列不能判斷是否有序(序列不唯一);

   3.該序列字母次序之間有矛盾,即有環存在。

思路:

這里應該用Kahn算法拓撲排序

每加入一條邊需要進行一次拓撲排序,如果拓撲排序發現有環,或者排序唯一那么就可以直接輸出結果,如果所有的邊輸入完成還不是上述兩種情況,那就輸出不能判斷。

這里的重點在於如何判斷拓撲排序的唯一性,這里運用了Kahn算法的思想。

Kahn算法:

1.找到入度為0的頂點加入棧中,然后提出棧頂元素,成為拓撲排序的一部分

2.除去與之相鄰所有邊並減少其度數,再次加入入度數為0的點循環往復,如果某一次棧已經空了而且沒有入讀為0的點,那就是存在有向環。

判斷唯一性:

那就得每次找到入度為0的頂點個數只能是1個,是0個說明存在環,多個說明拓撲排序不唯一。

由於每次只能有一個0度頂點,所以可以循環n次,依次找出拓撲排序中的每一位

需要注意的是,如果有一次找出了多個0度頂點,不能直接返回無序,只能暫時標記,因為可能之后的循環中存在環。

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 #include<stack>
 8 #include<map>
 9 #include<set>
10 #include<sstream>
11 #include<functional>
12 using namespace std;
13 typedef long long ll;
14 const int maxn = 100 + 10;
15 const int INF = 1e9 + 7;
16 int T, n, m, cases;
17 vector<int>Map[maxn];
18 int Count[maxn];
19 int ans[maxn];
20 int topo()
21 {
22     int cnt[maxn];
23     memcpy(cnt, Count, sizeof(Count));
24     int flag = 1;
25     for(int i = 0; i < n; i++)//為判斷順序是否唯一,有序的順序拓撲排序需要n次循環
26     {
27         int tot = 0;//度數為0的頂點的個數,超過一個說明拓撲排序一定不是唯一,可能不能確定,可能有環
28         int u;//記錄度數為0的點
29         for(int j = 0; j < n; j++)if(cnt[j] == 0){tot++, u = j;}
30         if(tot == 0)return 0;//有環
31         if(tot > 1)flag = -1;//一定不唯一,但是不能立馬退出,因為之后有可能是有環
32         ans[i] = u;//記錄拓撲排序順序
33         cnt[u] = -1;//已經排好,設成負數
34         for(int j = 0; j < Map[u].size(); j++)
35         {
36             int v = Map[u][j];
37             cnt[v]--;
38         }
39     }
40     return flag;
41 }
42 int main()
43 {
44     while(cin >> n >> m)
45     {
46         if(!n && !m)break;
47         string s;
48         int flag = 0;
49         for(int i = 0; i <= n; i++)Map[i].clear();
50         memset(Count, 0, sizeof(Count));
51         for(int i = 1; i <= m; i++)
52         {
53             cin >> s;
54             int u = s[0] - 'A';
55             int v = s[2] - 'A';
56             Map[u].push_back(v);
57             Count[v]++;//入度
58             if(flag)continue;//如果已經判斷出有序或者有環,就不做處理
59             int t = topo();
60             //cout<<t<<endl;
61             if(t == 0)//有環
62             {
63                 printf("Inconsistency found after %d relations.\n",i);
64                 flag = 1;
65             }
66             if(t == 1)//有序
67             {
68                 printf("Sorted sequence determined after %d relations: ",i);
69                 for(int i = 0; i < n; i++)printf("%c", ans[i] + 'A');
70                 printf(".\n");
71                 flag = 1;
72             }
73         }
74         if(!flag)printf("Sorted sequence cannot be determined.\n");
75     }
76     return 0;
77 }

 


免責聲明!

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



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