题意:给出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[30],into2[30]; //存储节点的入度数 int edge[30][30]; int ans[30],idx; //存储拓扑序列 int row,n,m; //row存储最后唯一判断出拓扑序列或者出现环的行数 int topo(int n){ int i,j=0,k,t=0,mark=1; while(j<n){ t=0; //统计入度为0的节点个数 for(i=0;i<n;i++){ if(into2[i]==0){ t++; if(t==1) k=i; } } //当入度为0的点大于1个时,也存在有环的情况!所以当t>1时,不能直接return 0,也要继续拓扑下去,看是否有当t=0的情况, if(t>1){ mark=0; } if(t==0) return -1; //没找到入度为0的点,有环存在 ans[j++]=k; into2[k]=-1; for(i=0;i<n;i++){ if(edge[k][i]) into2[i]--; } } return mark; } int main() { char a,b,c; char str[10]; int flag,tmp,u,v; while(scanf("%d%d",&n,&m)!=EOF){ if(n==0 && m==0) break; memset(edge,0,sizeof(edge)); memset(into,0,sizeof(into)); memset(into2,0,sizeof(into2)); memset(vis,0,sizeof(vis)); idx=0; flag=0;//flag=1为第一种情况,=-1为第二种情况,=0为第三种情况 for(int i=1;i<=m;i++){ scanf("%s",str); a=str[0];b=str[2]; if(flag==1 || flag==-1) continue; u=a-'A';v=b-'A'; edge[u][v]=1; into[v]++; into2[v]++; tmp=topo(n); if(tmp==-1){ row=i; flag=-1; //有环,即出现矛盾 } else if(tmp==0){ for(int q=0;q<30;q++) into2[q]=into[q]; continue; } else{ row=i; flag=1; } } if(flag==1){ printf("Sorted sequence determined after %d relations: ",row); for(int i=0;i<n;i++) printf("%c",ans[i]+'A'); printf(". "); } else if(flag==-1){ printf("Inconsistency found after %d relations. ",row); } else{ printf("Sorted sequence cannot be determined. "); } } return 0; }