题意:将给定的关系按从小到大排成一个唯一的序列。
思路:没输入一条边,使用拓扑排序判断能否得到最终结果,拓扑排序的结果有三种情形。
⑴如果该图存在环,那么给定的关系肯定互相矛盾。
⑵如果不存在环,但是拓扑排序结束后,排序得到的序列中的元素个数小于给定的元素个数,那么给定的关系不足以判断出全部元素的大小关系。
⑶如果拓扑出来的序列中的元素个数等于给定的元素个数,那么给出的关系可以判断出全部元素的大小 关系。
注意:此题要求所得序列唯一,若拓扑排序过程中栈中元素个数大于一个,则说明此时所得序列不唯一。
代码:
#include <iostream>
#include <cstdio>
#include <stack>
#include <vector>
using namespace std;
const int maxn = 30;
int n,m;
vector<int> list[maxn]; //邻接表
bool vis[maxn]; //记录元素是否出现
int ind[maxn]; //入度
int cnt; //当前出现的点的数量
char res[maxn]; //结果
/*
** 返回序列的元素个数,-1代表有环
*/
int TopSort(){
stack<int> st;
int d[maxn];
int f = 1;
for(int i = 0; i < n; i++){
d[i] = ind[i];
if(d[i] == 0 && vis[i]) st.push(i);
}
for(int i = 0; i < cnt; i++){
if(st.empty()) return -1;
if(st.size() > 1) f = 0;
int u = st.top(); st.pop(); res[i] = u + 'A';
for(int j = 0; j < list[u].size(); j++){
if(--d[list[u][j]] == 0) st.push(list[u][j]);
}
}
res[cnt] = '\0';
if(f) return cnt;
else return 0;
}
bool Input(){
int flag = 0;//记录拓扑排序返回的状态 -1存在环 0<flag<n表示不能确定
int k = 0; //在第k条关系能确定结果
char u,v;
cnt = 0;
cin>>n>>m;
if(n == 0 && m == 0)
return false;
for(int i = 0; i < n; i++) {
list[i].clear();
ind[i] = 0;
vis[i] = false;
}
for(int i = 0; i < m; i++){
cin>>u;
getchar();
cin>>v;
list[u-'A'].push_back(v-'A');
ind[v-'A']++;
if(!vis[u-'A']) {vis[u-'A'] = true; cnt++;}
if(!vis[v-'A']) {vis[v-'A'] = true; cnt++;}
if(flag != -1 && flag != n) {flag = TopSort(); k = i;}
}
if(flag == -1){
printf("Inconsistency found after %d relations.\n",k+1);
}
else if(flag < n){
printf("Sorted sequence cannot be determined.\n");
}
else{
printf("Sorted sequence determined after %d relations: %s.\n",k+1,res);
}
return true;
}
int main(){
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
while(Input());
return 0;
}