
题意:给出n个字符,m对关系,让你输出三种情况:
1.若到第k行时,能判断出唯一的拓扑序列,则输出:
Sorted sequence determined after k relations: 序列
2.若到第k行,出现环,则输出:
Inconsistency found after k relations.
3.若直到m行后,仍判断不出唯一的拓扑序列,则输出:
Sorted sequence cannot be determined.
思路:每读取一行,就进行一次拓扑排序,为防止影响之后的拓扑排序,拓扑排序时用的入度数组为into2。
如果拓扑排序能得出唯一的序列,即为第一种情况,之后只要直接读取数据,不必操作。
如果拓扑排序时不存在入度为0的节点,则为第二种情况,之后只要直接读取数据,不必操作。
如果拓扑排序时有多个入度为0的节点,则继续读取数据再操作,直至读完m行。
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm> using namespace std;
int into[],into2[]; //存储节点的入度数
int edge[][];
int ans[],idx; //存储拓扑序列
int row,n,m; //row存储最后唯一判断出拓扑序列或者出现环的行数 int topo(int n){
int i,j=,k,t=,mark=;
while(j<n){
t=;
//统计入度为0的节点个数
for(i=;i<n;i++){
if(into2[i]==){
t++;
if(t==)
k=i;
}
}
//当入度为0的点大于1个时,也存在有环的情况!所以当t>1时,不能直接return 0,也要继续拓扑下去,看是否有当t=0的情况,
if(t>){
mark=;
}
if(t==)
return -; //没找到入度为0的点,有环存在
ans[j++]=k;
into2[k]=-;
for(i=;i<n;i++){
if(edge[k][i])
into2[i]--;
}
}
return mark;
}
int main()
{
char a,b,c;
char str[];
int flag,tmp,u,v;
while(scanf("%d%d",&n,&m)!=EOF){
if(n== && m==)
break;
memset(edge,,sizeof(edge));
memset(into,,sizeof(into));
memset(into2,,sizeof(into2));
memset(vis,,sizeof(vis));
idx=;
flag=;//flag=1为第一种情况,=-1为第二种情况,=0为第三种情况
for(int i=;i<=m;i++){
scanf("%s",str);
a=str[];b=str[];
if(flag== || flag==-)
continue;
u=a-'A';v=b-'A';
edge[u][v]=;
into[v]++;
into2[v]++;
tmp=topo(n);
if(tmp==-){
row=i;
flag=-; //有环,即出现矛盾
}
else if(tmp==){
for(int q=;q<;q++)
into2[q]=into[q];
continue;
}
else{
row=i;
flag=;
}
}
if(flag==){
printf("Sorted sequence determined after %d relations: ",row);
for(int i=;i<n;i++)
printf("%c",ans[i]+'A');
printf(".\n");
}
else if(flag==-){
printf("Inconsistency found after %d relations.\n",row);
}
else{
printf("Sorted sequence cannot be determined.\n");
} }
return ;
}