这道题在我看来之所以采用拓扑排序,是因为数据所构成的图中存在环,而拓扑排序正好能巧妙解决这个问题,
再谈谈这个题的思想:
将两个节点构成的边存入一个图中,并且记录每一个节点的入度,进行拓扑排序:
将入度为0的节点先加入队列中,如果队列中节点数大于一,则说明存在节点无法判断其大小关系,取队首节点,并将该节点压入vector中,(因为要计算最后结果),删除队首节点,并删除与该节点相连接的节点所构成得边,如果删除之后相连接的节点的入度也变为0,则加入队列中。如此往复直至最后变为空队列,如果此时vector中的节点个数小于总的节点个数,则说明存在环。(因为如果存在环,则环中的元素永远也不可能入度==0)
实现代码:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
int graph[30][30];
int in[30];
vector<int> v;
int topsort(int n){
queue<int> q;
v.clear();
//因为之后还要计算,所以将in数组中的元素先存放的另一个数组中
int tmp[30];
for(int i=0;i<n;i++)
tmp[i]=in[i];
for(int i=0;i<n;i++){
if(in[i]==0) q.push(i);
}
int flag=0;
while(!q.empty()){
if(q.size()>1) flag=1;
int t=q.front();
q.pop();
v.push_back(t);
for(int i=0;i<n;i++){
if(graph[t][i]){
tmp[i]--;
if(tmp[i]==0) q.push(i);
}
}
}
if(v.size()<n) return 0; //有环
if(flag) return 1; //不能判断。
return 2;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF,n,m){
memset(graph,0,sizeof(graph));
memset(in,0,sizeof(in));
int flag=0;char a,b,c;
for(int i=1;i<=m;i++){
scanf(" %c%c%c",&a,&b,&c);
if(flag) continue;
in[c-'A']++;
graph[a-'A'][c-'A']=1;
int t=topsort(n);
if(t==2){
printf("Sorted sequence determined after %d relations: ",i);
for(int i=0;i<n;i++)
printf("%c",'A'+v[i]);
printf(".\n");
flag=1;
}
if(t==0){
printf("Inconsistency found after %d relations.\n",i);
flag=1;
}
}
if(flag==0){
printf("Sorted sequence cannot be determined.\n");
}
}
return 0;
}