这道题的确考查拓扑排序考查的挺全的
第一:是否可拓扑
第二:是否有唯一拓扑序
第三:输出拓扑序
是否可排序:当删点的时候度为0的点不是全部的点的时候,就一定出现了环
是否唯一:利用 dfs 判断一个图是否可以排序可以用删点的方法,当出现两个及以上 0 的入度的点的时候,便是不唯一
输出的话就排下序列然后输出就OK了..
只是我不是这么做的...
我之前只会 dfs 输出拓扑序,所以,判环这个任务就在加边的时候完成了
R[i][j] = 1 代表 i 比 j 大, -1 反之,0代表不缺定
每次加边的时候利用已经存在的关系递归的加下去。若出现冲突,则不能排序。若 R 数组中除 R[i][i] 之外都填满的时候,就完成了排序,DFS 一遍输出。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;
int R[30][30];// R i to j 1 is big -1 is small
char s[50000][6];
int n,m;
bool OK()
{
int m=n;
for(int i=0;i<m;i++)
{
for(int j=0;j<m;j++)
{
if(i==j)
continue;
if(R[i][j]==0)
return false;
}
}
return true;
}
vector<int> topo;
int used[30];
void dfs(int x)
{
used[x]=1;
for(int i=0;i<n;i++)
{
if(!used[i]&&R[x][i]==1)
dfs(i);
}
topo.push_back(x);
}
// a small b big
bool addR(int a,int b)
{
if(R[a][b]==1)
return false;
if(R[a][b]==-1)
return true;
R[a][b]=-1;
R[b][a]=1;
int flag=true;
for(int j=0;j<n;j++)
{
if(R[a][j]==1)
flag&=addR(j,b);
if(R[b][j]==-1)
flag&=addR(a,j);
}
return flag;
}
int main()
{
while(cin>>n>>m&&(n!=0||m!=0))
{
memset(R,0,sizeof(R));
memset(used,0,sizeof(used));
topo.clear();
for(int i=0;i<m;i++)
scanf("%s",s[i]);
bool can=false;
for(int i=0;i<m;i++)
{
int small=s[i][0]-'A';
int big=s[i][2]-'A';
if(!addR(small,big))
{
can=true;
printf("Inconsistency found after %d relations.\n",i+1);
break;
}
if(OK())
{
can=true;
for(int j=0;j<n;j++)
if(!used[j])
dfs(j);
char res[30];
for(int j=0;j<n;j++)
res[j]='A'+topo[j];
res[n]='\0';
printf("Sorted sequence determined after %d relations: %s.\n",i+1,res);
break;
}
}
if(!can)
printf("Sorted sequence cannot be determined.\n");
}
return 0;
}