poj1094 拓扑排序

Sorting It All Out
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 24092 Accepted: 8321

Description

An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from smallest to largest. For example, the sorted sequence A, B, C, D implies that A < B, B < C and C < D. in this problem, we will give you a set of relations of the form A < B and ask you to determine whether a sorted order has been specified or not.

Input

Input consists of multiple problem instances. Each instance starts with a line containing two positive integers n and m. the first value indicated the number of objects to sort, where 2 <= n <= 26. The objects to be sorted will be the first n characters of the uppercase alphabet. The second value m indicates the number of relations of the form A < B which will be given in this problem instance. Next will be m lines, each containing one such relation consisting of three characters: an uppercase letter, the character "<" and a second uppercase letter. No letter will be outside the range of the first n letters of the alphabet. Values of n = m = 0 indicate end of input.

Output

For each problem instance, output consists of one line. This line should be one of the following three:

Sorted sequence determined after xxx relations: yyy...y.
Sorted sequence cannot be determined.
Inconsistency found after xxx relations.

where xxx is the number of relations processed at the time either a sorted sequence is determined or an inconsistency is found, whichever comes first, and yyy...y is the sorted, ascending sequence.

Sample Input

4 6
A<B
A<C
B<C
C<D
B<D
A<B
3 2
A<B
B<A
26 1
A<Z
0 0

Sample Output

Sorted sequence determined after 4 relations: ABCD.
Inconsistency found after 2 relations.
Sorted sequence cannot be determined.
拓扑排序!详见代码
#include<iostream>
#include<cstring>
using namespace std;

int n,m;  //n结点下限,m关系对
char top_out[26];  //排序输出列表
int po=0;  //输出列表的指针

typedef class degree
{
public:
	int in;      //入度
	char to[26];   //记录指向的所有顶点,以便删除出度的操作
	int pt;    //数组to的指针
};

int top_sort(degree alph[],bool mark[],int num)
{
	/*假设图G的当前子图为F*/

	memset(top_out,'\0',sizeof(top_out));
	po=0;
	
	int del_n=0;
	int zero=0;  //记录图F中入度为0的结点个数
	for(int i='A';i<'A'+n;i++)
		if(mark[i] && !alph[i].in)
			zero++;

	bool flag=false;
	while(zero>0)
	{
		if(zero>1)  //图F的无前驱结点的个数不唯一,排序无法确定
			flag=true;  //考虑到"矛盾"的优先性,避免在多个0入度结点情况下,最后一步输入刚好出现环(此时为矛盾)
		                //所以这里先不返回值,而是先标记,执行拓扑,根据情况决定返回值

		for(int k='A';k<='A'+n;k++)   //寻找图F的唯一的前驱结点
			if(mark[k] && !alph[k].in)
			{
				mark[k]=false;       //删除图F的唯一无前驱结点k
				del_n++;            //记录删除的结点数
				top_out[po++]=k;    //k记录到排序输出列表
				for(int i=0;i<alph[k].pt;i++)   //删除结点k的所有出度边
					alph[ alph[k].to[i] ].in--;
				break;
			}

		zero=0;
		for(int j='A';j<='A'+n;j++)
			if(mark[j] && !alph[j].in)
				zero++;
	}

    if(flag && del_n==num)
		return 3;
	if(del_n<num)   //说明图F存在有向环,矛盾,与0入度结点的多少无关。因为矛盾优先
		return 2;
	if(!flag && del_n==num && del_n<n)  //图F能排序,但不能确定图G是否能排序,还需继续输入观察
		return 3;
	if(!flag && del_n==n)    //图G能排序
		return 1;
}

int main(void)
{
	int num;      //标记前n个字母出现个数,用于最终检查是否前n个字母均已被读入
	     //*_t[]是用于备份的额外数组
	bool mark['Z'+1],mark_t['Z'+1];  //标记当前图G所使用的字母(结点)
	degree alph['Z'+1],alph_t['Z'+1];   

	while(true)
	{
		/*Input*/

		cin>>n>>m;

		if(!n||!m)
			break;
		
		/*Initial*/

		memset(mark,false,sizeof(mark));
		memset(mark_t,false,sizeof(mark_t));
		num=0;

		for(int k='A';k<'A'+n;k++)
		{
			alph[k].in=alph_t[k].in=0;
			alph[k].pt=alph_t[k].pt=0;
			memset(alph[k].to,'\0',sizeof(alph[k].to));
			memset(alph_t[k].to,'\0',sizeof(alph_t[k].to));
		}
		
		/*Structure Maps*/

		char x,symbol,y;  //临时变量
		bool flag=false;
		bool sign=false;
		int value;   //记录拓扑返回的值
		int step;   //记录当前情况发生的步骤
		for(int pair=1;pair<=m;pair++)
		{
			cin>>x>>symbol>>y;

			if(x>='A'+n || y>='A'+n)  //当输入的结点不在前n个字母范围内时
				sign=true;       //不再进行拓扑,单纯检查后续输入是否把前n个字母都输入了
				                 //为了区分非前n个字母的字母的输入时间,是在确认了排序或矛盾之前还是之后
			                     //在确认 排序或矛盾之前:flag=false,sign=true
			                     //在确认 排序或矛盾之后:flag=true,sign=true

			if(!mark[x] && x<'A'+n)
				num++;
			if(!mark[y] && y<'A'+n)
				num++;

			if(!flag && !sign)
			{
				value=0;

			    mark[x]=mark[y]=true;        //顶点标记
			    mark_t[x]=mark_t[y]=true;

			    alph[y].in++;                //入度标记
			    alph_t[y].in++;

			    alph[x].to[ alph[x].pt++ ]=y;        //指向标记 & 指针移动
			    alph_t[x].to[ alph_t[x].pt++ ]=y;

			/*Top-Sort & Sign*/
				
				value=top_sort(alph_t,mark_t,num);  //每次输入后图都被更新,要重新拓扑
			    if(value==1)       //排序确认
				{
			     	step=pair;    //记录确认排序的位置
			    	flag=true;    //不再对后续输入处理
				}
		    	else if(value==2)  //矛盾
				{
			    	step=pair;    //记录矛盾发生的位置
			    	flag=true;    //不再对后续输入处理
				}
		    	else if(value==3 && pair<m)  //排序(暂时)无法确认,需继续处理后续输入 
			    	for(int k='A';k<'A'+n;k++)        //数据还原
					{
				    	mark_t[k]=mark[k];
				    	alph_t[k].in=alph[k].in;
					}

				if(pair==m && value==0)
					value=3;
			}

			if(sign && !flag && num==n)  //在确认 排序或矛盾之前,当存在有非前n个字母的结点时的"矛盾"
			{
				step=pair;
				value=2;
			}
			else if(sign && !flag && pair==m && num<n) //在确认 排序或矛盾之前,当存在有非前n个字母的结点时的"无法确认排序"
				value=3;
		}

		if(value==1)
		{
			cout<<"Sorted sequence determined after "<<step<<" relations: ";
			for(int i=0;i<po;i++)
				cout<<top_out[i];
			cout<<'.'<<endl;
		}
		else if(value==2)
			cout<<"Inconsistency found after "<<step<<" relations."<<endl;
		else if(value==3)
			cout<<"Sorted sequence cannot be determined."<<endl;
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值