Description:
一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D。在这道题中,我们将给你一系列形如A<B的关系,并要求你判断是否能够根据这些关系确定这个数列的顺序。第一行有两个整数n,m,n表示需要排序的元素数量,2<=n<=26,第1到n个元素将用大写的A,B,C,D....表示。m表示将给出的形如A<B的关系的数量。
接下来有m行,每行有3个字符,分别为一个大写字母,一个<符号,一个大写字母,表示两个元素之间的关系。
若根据前x个关系即可确定这n个元素的顺序yyy..y(如ABC),输出
Sorted sequence determined after xxx relations: yyy...y.
若根据前x个关系即发现存在矛盾(如A<B,B<C,C<A),输出
Inconsistency found after 2 relations.
若根据这m个关系无法确定这n个元素的顺序,输出
Sorted sequence cannot be determined.
Analysis:
每次输入就进行一次拓扑排序,找最长路,并判断有没有环 。等n个点都出现后,再判断是否有矛盾,输入结束后上面两种情况没有出现,那就是无法确定顺序。
举个栗子,如果已知A<B,A<C,B<C,则正确的顺序应为A<B<C,所以是要找最长路。
Code
#include <bits/stdc++.h>
using namespace std;
const int maxn=30;
vector<int> G[maxn];
char ops[10];
int n,m,idx,indeg[maxn],tmp[maxn],stk[maxn],top,d[maxn];//d[i]为以i结尾的最长路径
bool circle,certain;
inline void add_edge(int from,int to){
G[from].push_back(to);
++indeg[to];
}
void topo_sort(int now){
// tmp 临时保存入度
queue<int> Q;
int dep = 1;//dep为当前DAG上的最长路径的长度
for(int i = 1;i <= n;i++)d[i]=0;
for(int i = 1;i <= n;i++){
tmp[i] = indeg[i];
if(!tmp[i])Q.push(i),d[i] = 1;
}
top = 0;
while(Q.size()){
int u = Q.front();Q.pop();
stk[++top]=u; //记录ans
for(int i=0;i<G[u].size();i++){
int v = G[u][i];
--tmp[v];
if(!tmp[v])Q.push(v);
d[v] = max(d[v],d[u]+1); //DP拓扑排序
dep = max(dep,d[v]);
}
}
if(top != n)circle = 1,idx = now;
else if(dep == n)certain = 1,idx = now;
}
void solve(){
for(int i = 1;i <= m;i++){
scanf("%s",ops+1);
if(circle||certain)break;
int from=ops[1]-'A'+1,to=ops[3]-'A'+1;
add_edge(from,to);
topo_sort(i); //每加一条边,进行一次topo
}
if(certain){
printf("Sorted sequence determined after %d relations: ",idx);
for(int i = 1;i <= n;i++)printf("%c",stk[i]+'A'-1);
printf(".
");
}
else if(circle)printf("Inconsistency found after %d relations.
",idx);
else printf("Sorted sequence cannot be determined.
");
}
int main(){
scanf("%d%d",&n,&m);
solve();
return 0;
}