POJ 1094
//拓扑排序的经典题目
//此题切忌:无法排序的情况下也可能出现环的情况
#include <iostream>
#include <string>
using namespace std;
#define arraysize 30
int map[arraysize][arraysize]; //存储邻接阵
int indegree[arraysize]; //存储节点入度
char resultset[arraysize]; //存储结果
int n,m;
int topsort()
{
int i,j,k;
memset(indegree,0,sizeof(indegree));
memset(resultset,0,sizeof(resultset));
for(i=1;i<n+1;++i)
{
for(j=1;j<n+1;++j)
{
if(map[i][j]==1)
indegree[j]++;
}
}
int num = 0;
bool isOnly = false; //用于标记拓扑排序是否唯一
for(i=1;i<n+1;++i)
{
int only = 0; //判断拓扑排序是否唯一
for(j=1;j<n+1;++j)
{
if(indegree[j]==0)
{
only++;
if(only>1) //在一次排序中出现了两个入度为0的节点,表明拓扑排序不唯一,不要立即返回,可能出现冲突情况,需要接着判断
isOnly = true;
}
}
if(only==0) //拓扑排序中环路的判断方式:一个入度为0的节点未找到,代表有环
return 0;
for(j=1;j<n+1;++j)
{
if(indegree[j]==0)
{
resultset[num] = 'A'+j-1;
num++;
indegree[j]--;
for(k=1;k<n+1;++k)
{
if(map[j][k]==1)
indegree[k]--;
}
break;
}
}
}
resultset[num]='\0'; //此出别忘了添加'\0'
if(isOnly) //拓扑排序不唯一
return 1;
else if(num==n && !isOnly) //可以进行排序
return 2;
}
int main()
{
freopen("1.txt","r",stdin);
int i,j;
char str[4];
int result;
bool isOver;
while(cin>>n>>m)
{
if(n==0 && m==0)
break;
isOver = false;
memset(map,0,sizeof(map));
for(i=1;i<m+1;++i)
{
cin>>str;
map[str[0]-'A'+1][str[2]-'A'+1] =1;
result= topsort(); //边输入边进行拓扑排序
if(result==0) //产生了环
{
isOver = true;
printf("Inconsistency found after %d relations.\n",i);
for(j=i+1;j<m+1;++j)
cin>>str;
break;
}
else if(result==1) //拓扑排序不唯一
continue;
else if(result==2) //可以进行排序
{
isOver = true;
printf("Sorted sequence determined after %d relations: %s.\n",i,resultset);
for(j=i+1;j<m+1;++j)
cin>>str;
break;
}
}
if(!isOver)
{
printf("Sorted sequence cannot be determined.\n");
}
}
return 0;
}