poj-1094 Sorting It All Out[拓扑排序]

感觉需要注意的细节有点多。

(1)先判断是否有环  用used表示能拓扑的点 vis表示能搜索到的点

假如两者总数不等说明有环。

(2)再判断拓扑序是否唯一

假如一次寻找0入度节点有多个即不唯一

/*
所谓不同值的递增排序的序列,是通过一个小于号的运算符,
找出从最小的到最大的元素。例如,有一个有序的序列A,B,C,D。
这就意味着,A<B,B<C,C<D。对于这一道问题,
我们将为您提供一系列式如A<B的序列,想请您确定序列能不能确定下来
 输入 输入包含多个问题的实例。
 每个实例的第一行都包含两个正整数n和m,
 第一个值n表明了排序对象的数量,其中2=<n<=26。
 这些排序对象将是大写字母表里的前n个字母。
 第二个值m表示有m个类似于A<B的关系。接下来的m行,
 每行包含一个类似这样的关系A<B。
 这些字母不会超出字母表的前n个字母的范围。
 当n=0,m= 0时表示输入结束。 输出 对于每个问题实例,
 都应输出下面三行之一: 
 Sorted sequence determined after xxx relations: yyy...y.
  Sorted sequence cannot be determined. 
  Inconsistency found after xxx relations. 
  其中xxx表示排序顺序或者出现矛盾在xxx个关系后能够判定,以先到者为准,
  而yyy ...y是一个递增的序列。 
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <queue>
#define MAX_N 28
using namespace std;
int indeg[MAX_N];
char seq[MAX_N];
vector<int> g[MAX_N];
int n;
void init()
{//初始化
	for(int i=0;i<MAX_N;++i)
		indeg[i]=-1,g[i].clear();
}
void add_edge(int u,int v)
{//加边
	if(indeg[u]==-1) indeg[u]=0;
	if(indeg[v]==-1) indeg[v]=1;
	else ++indeg[v];
	g[u].push_back(v);
}
int judge()
{
	int ind[MAX_N];
	int used[MAX_N];//记录拓扑过的点
	int vis[MAX_N];//记录能访问的点
	memset(used,0,sizeof(used));
	memset(vis,0,sizeof(vis));
	for(int k=0;k<n;++k)//复制入度
		ind[k]=indeg[k];
	queue<int> que;
	for(int k=0;k<n;++k)
		if(!ind[k])//压0入度点入队列
		{
			used[k]=vis[k]=1;
			que.push(k);
		}
	int cnt=0,only=1;
	if(que.size()>1)
		only=0;
	else if(que.size()==0)
		return 2;
	//printf("%d %d\n",que.size(),que.front());
	while(!que.empty())
	{
		int u=que.front();que.pop();
		vis[u]=used[u]=1,seq[cnt++]=u+'A';
		//printf("%d\n",u);
		int flag=0;
		for(int i=0;i<g[u].size();++i)
		{
			int v=g[u][i];
			vis[v]=1;
			--ind[v];
			if(!used[v]&&!ind[v])
				que.push(v),++flag;
		}
		if(flag>1)
			only=0;
	}
	seq[cnt]='\0';
	int ucnt=0,gcnt=0;
	for(int i=0;i<n;++i)
	{
		if(vis[i]) ++gcnt;
		if(used[i]) ++ucnt;
	}
	if(gcnt!=ucnt)//假如拓扑的点和能访问的点不一致说明有环
		return 2; 
	if(cnt==n&&only)
		return 1;
	return 0;
}
int main()
{
	int m;
	while(~scanf("%d%d",&n,&m))
	{
		if(n==0&&m==0)
			break;
		char in[5];
		int flag=0,loc;
		init();
		for(int i=1;i<=m;++i)
		{
			//printf("%d\n",i);
			scanf("%s",in);
			if(!flag)
			{
				add_edge(in[0]-'A',in[2]-'A');
				int t=judge();
				if(t==1)
					flag=1,loc=i;
				if(t==2)
					flag=2,loc=i;
			}
		}
		if(flag==1)
			printf("Sorted sequence determined after %d relations: %s.\n",loc,seq);
		else if(flag==2)
			printf("Inconsistency found after %d relations.\n",loc );
		else printf("Sorted sequence cannot be determined.\n");
	}
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值