http://poj.org/problem?id=1094
题目给出n,m表示有n个字母 要排序 A.B.C..D..前n个,
m条关系 X<Y
在读入m条关系的过程中
情况【1】假如读到第i条时,可以用前i条边确定出 字典序前n个字母之前的大小关系,请输入序列,以及当前的i
情况【2】假如读到第i条时,可以用前i条边确定出 当前的边在一起是不可能构成一个有序序列,请输入当前的i,以及“不可能构成有序序列”
情况【3】假如读完了m条后,发现还没法确定 一个关于前n个字母有序的序列(少一个都不行),也暂时没造成矛盾,请输入 “不能准确判断”
解决方案:
把每次输入的关系看成一条有向边,map[u][v]=1;并且记下 点V的入度(拓扑排序用), 然后进行一次拓扑排序,
如果是情况【1】, 则输出情况1的答案;接下来直接读取完剩下的条件,不作处理;
如果是情况【2】,同上
如果是情况【3】,继续读入下一条边直到 m条边处理完;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
using namespace std;
int map[28][28];
int indegree[28];
int cun=0;
int qq[28];
int mark;// 表示已经得到确定结果了,剩下的输入只需要读入不需要考虑
int Topo(int n)
{
int i,j;
int cun=0;
int ret=1; //0表示有环,-1表示无序,1表示有序
int temp_du[28]; //a copy of indegree
for (i=1;i<=n;i++)
temp_du[i]=indegree[i];
int zero=-1;// index of 度数为0的顶点
for (i=1;i<=n;i++)
{
int num=0; // num of 度数为0的顶点
for (j=1;j<=n;j++)
{
if (temp_du[j]==0)
{
num++;
zero=j;
}
}
if (num==0) //有环
return 0;
if (num>1) //仅仅指当前条边所得到的结果是无序的,可能再加一些边后得到有序或者 有环的结果
{
ret=-1; //0表示有环,-1表示无序,1表示有序
}
qq[cun++]=zero; //度为0的点入队;
temp_du[zero]=-1; // 删除该点;
for (j=1;j<=n;j++)
{
if (map[zero][j]==1)
{
temp_du[j]--;
}
}
}
return ret;
}
char str[15];
int main()
{
int n,m;
int i,j;
while(scanf("%d%d",&n,&m)!=EOF)
{
if (!n&&!m) break;
memset(map,0,sizeof(map));
memset(indegree,0,sizeof(indegree));
mark=0; //结束标记
for (i=1;i<=m;i++)
{
scanf("%s",str);
if (mark) continue; //不用继续处理
int u=str[0]-'A'+1;
int v=str[2]-'A'+1;
map[u][v]=1;
indegree[v]++;
int s=Topo(n);
if (s==0) //有环,矛盾
{
printf("Inconsistency found after %d relations.\n",i);
mark=1; //以后的输入不再处理
}
if (s==1)
{
printf("Sorted sequence determined after %d relations: ",i);
for (j=0;j<n;j++)
{
printf("%c",qq[j]+'A'-1);
}
printf(".\n");
mark=1;
}
}
if (!mark)
printf("Sorted sequence cannot be determined.\n");
}
return 0;
}