题目分析
拓扑排序的情况
-
拓扑排序不存在
无法确定m个元素的关系,即拓扑排序无解,无解的判断方法是:
如果队列已空,还有点未入队,那么这些点的入度都不为0,说明图不是DAG,不存在拓扑排序
即拓扑排序后的元素长度不等于给定的元素长度(判断方式) -
拓扑排序不唯一
若ans.size() == n,即拓扑排序存在,还需要判断该拓扑排序是否唯一,
//判定方法:判定是否存在某一时刻,用于拓扑排序的队列的长度不为1,若不为1,证明当前有多个入度为0的点可供选择遍历,故拓扑排序不唯一。
整体思路
一边读入关系一边进行一次拓扑排序,方便找到遍历了前x个关系时,唯一拓扑排序或存在环的情况出现的x值。
代码实现
#include<bits/stdc++.h>
using namespace std;
int n,m;
string s;
vector<int>graph[105];
int ind[30];
vector<int>ans;
int check()
{
ans.clear();
bool flag=false;
int rudu[30]={0};
for(int i=1;i<=26;i++)
{
rudu[i]=ind[i];
}
queue<int>q;
//将起点压入队列
for(int i=1;i<=n;i++)
{
if(rudu[i]==0)
q.push(i);
}
while(!q.empty())
{
if(q.size()>1) flag=1;
int u=q.front();
q.pop();
ans.push_back(u);
//遍历与此点相连的所有点
for(int i=0;i<graph[u].size();i++)
{
//相连的点的入度-1
rudu[graph[u][i]]--;
//当入度为0时,放入队列中
if(rudu[graph[u][i]]==0)
q.push(graph[u][i]);
}
}
//如果形成的拓扑排序的点的个数不等于所有数的个数,即有点没排,没入队,即不存在拓扑排序,有环
if(ans.size()!=n) return -1;
if(flag) return 0;
return 1;
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>s;
int u=s[0]-'A'+1;
int v=s[2]-'A'+1;
//邻接矩阵存储
graph[u].push_back(v);
//记录入度
ind[v]++;
int judge=check();
//存在环 即矛盾
if(judge==-1)
{
cout<<"Inconsistency found after " << i << " relations.";
return ;
}
// 能确定唯一顺序
else if(judge==1)
{
cout << "Sorted sequence determined after " << i << " relations: ";
for(int i=0;i<ans.size();i++)
{
char tmp=ans[i]+'A'-1;
cout<<tmp;
}
cout<<".";
return ;
}
}
//无法决定唯一顺序
cout<< "Sorted sequence cannot be determined.";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}