题目大意:给出n个大写字母一系列的大小关系,问给出第几个时能确定其全部关系(是否确定全部大小),关系有三种:有环矛盾、不确定、确定。
解题思路:对前i种已给出的关系进行拓扑排序,判断是否能排出。此处用队列实现~
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <list>
using namespace std;
const int maxn = 30;
int in[maxn];
vector<int> v[maxn],tv[maxn]; //v[i]表示与i点相连的点都存在该向量中
int tag1,tag2,tag3;
int n,m;
void topoSort(int x) //对第x次输入及之前进行排序
{
queue<int> Q;
char res[30];
memset(res,0,sizeof(res));
tag3 = 0;//标记队列中还有多个入度为0的点时,当前还不确定是否能排好序
int tin[maxn];
for(int i = 0; i < n; i++)
{
tin[i] = in[i];//复制每个点的入度
tv[i].resize(v[i].size()); //复制与i点相连的点的个数
memcpy(&tv[i][0],&v[i][0],v[i].size()*sizeof(int));//复制v[i]的内容
}
for(int i = 0; i < n; i++)
{
if(!tin[i])
{
Q.push(i);
tin[i]--;
}
}
int sum = 0;
while(!Q.empty())
{
if(Q.size() > 1) tag3 = 1;
int t = Q.front();
Q.pop();
res[sum++] = t+'A';
tin[t]--;
for(int i = 0; i < tv[t].size(); i++)
{
tin[tv[t][i]]--;
if(!tin[tv[t][i]]) Q.push(tv[t][i]);
}
}
if(sum < n)
{
tag1 = 1;
printf("Inconsistency found after %d relations.\n",x);
}
else if(tag3) return;
else
{
tag2=1;
printf("Sorted sequence determined after %d relations: %s.\n",x,res);
}
}
int main()
{
char s[5];
while(scanf("%d%d",&n,&m) != EOF)
{
if(!(m+n)) break;
memset(in,0,sizeof(in));
for(int i = 0; i < maxn; i++)
v[i].clear();
tag1 = tag2 = 0;//标记是否确定能排序以及是否确定不能排序
for(int i = 1; i <= m; i++)
{
scanf("%s",s);
v[s[0]-'A'].push_back(s[2]-'A');
in[s[2]-'A']++;
if(!tag1&&!tag2) topoSort(i);
}
if(!tag1&&!tag2)
puts("Sorted sequence cannot be determined.");
}
return 0;
}