题意: 根据所给的关系(即A<B之类的), 判断是否能在给出某一组关系之后确定给定的所有字母的顺序(字母总数为n, 指前n个字母, 均为daxie), 若能则输出(根据题目输出), 若在给出某一组关系之后出现矛盾(例如 A<B B<C C<A, 矛盾, 形成环路)则输出(根据题目输出) , 所有关系均输入后仍然不能判断出矛盾或者有序, 则输出"Sorted sequence cannot be determined.".
解决: 明显的拓扑排序, 每组关系输入后都进行一次拓扑排序,根据返回结果确定输出
Code:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 100;
int vis[maxn], num[maxn], d[maxn], dis[maxn][maxn];
int n, m ;
char c[5];
void init(){
memset(dis, 0, sizeof(dis));
memset(vis, 0, sizeof(vis));
}
int topology(){
int i, j, k=0;
memset(d, -1, sizeof(d));
for(i=0; i<n; i++){
if(vis[i]){
k++;
if(d[i]==-1) d[i]=0;
for(j=0; j<n; j++){
if(dis[i][j]) {
if(d[j]==-1) d[j]=0;
d[j]++;
}
}
}
}
int u, cnt=0, p=0;
while(true){
u=-1;
for(i=0; i<n; i++){
if(!d[i]) {
u = i;
p++;//记录d[i]=0的个数, 每次都应该只有一个d[i]=0
}
}
if(u==-1) break;
d[u] = -1;
num[cnt++] = u;
for(i=0; i<n; i++){
if(dis[u][i]) d[i]--;
}
}
if(cnt<k) return 1;//矛盾
else if(p>k) return 0;//暂时满足要求
else if(cnt==n)return 2;//完成
return 0;
}
int main()
{
int i, j, k;
//freopen("in.txt", "r", stdin);
while(~scanf("%d %d", &n, &m), m||n){
bool flag=false;
init();
int v=0;
for(i=1; i<=m; i++){
scanf("%s", c);
int a = c[0]-'A';
int b = c[2]-'A';
if(v) continue;
vis[a] = vis[b] = 1;
dis[a][b]=1;
int k = topology();
if(k==1) { // 矛盾 ->存在环
flag = true;
v=i;
} else if(k==2){//已经成功排序
v=i;
}
}
if(v) {
if(flag){
printf("Inconsistency found after %d relations.\n", v);
} else {
printf("Sorted sequence determined after %d relations: ", v);
for(i=0; i<n; i++){
printf("%c", num[i]+'A');
}
printf(".\n");
}
} else {
printf("Sorted sequence cannot be determined.\n");
}
}
return 0;
}