poj1094 Sorting It All Out

本文详细介绍了如何通过算法解决具有复杂关系的排序问题,包括唯一序列、矛盾和无法确定序列的情况。通过实例分析和代码实现,阐述了排序过程中可能出现的三种结果,并提供了相应的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接:http://poj.org/problem?id=1094 
题意:题目的意思很简单。就是给定一些字母之间的先后关系,然后对其排序。 排序的结果有三种:一、唯一的序列;二、存在矛盾(即有环);三、无法确定序列。总的来说是这三种,但每种又有好多种情况!!!这个是本题的难点,要把所有的情况都搞清楚。然后我说一下具体的情况:1、序列唯一。如果在输入了w条边后,序列已确定,即包含了所有前n个顶点,即便后面有矛盾,序列依旧确定;2、存在矛盾,即有环存在。如果既有多个无前驱节点(即无法确定排序)又有环,则先输出矛盾。3、无法确定序列。如果输入的字母大于了最后第n个字母,则排序无法确定。如果最终输入的最大的字母任然小于第n个字母,则无法排序。如果排序完毕,无矛盾,但是字母数量没达到n个,则无法确定排序。如果一个图的子图存在多个无前驱节点,则也无法确定排序(前提是图中无矛盾)。
这个题的图是随着边条数的增加不断更新的,然后边做判断。

#include<iostream>
using namespace std;
#define  MAXN 2500
struct Edge
{
  int l,r;
}edge[MAXN];
int relate[30][30];
char sans[30];  //ans再改为sans后,就能输出ABCD了
int flag;
int all_edge_num,edge_num,lett_num,rela_num;
void  Topo_Sort()
{
  int i,j,u,zeroflag=0,count=1,temp_lett_num=0,zerodegree_num=0;
  int into[30];
  flag=1;
  for(i=1;i<=lett_num;i++)
	  into[i]=-2;
  memset(sans,'0',sizeof(sans));
  for(i=1;i<=edge_num;i++)
	{
		into[edge[i].l]=0;
		into[edge[i].r]=0;
	}
  for(i=1;i<=lett_num;i++)
	  if(into[i]==0)
		temp_lett_num++;
  for(i=1;i<=edge_num;i++)
	if(relate[edge[i].l][edge[i].r]>0)
		into[edge[i].r]++;
  for(i=1;i<=lett_num;i++)
	if(into[i]==0)	
	  zerodegree_num++; //入度为0的点的个数
  if(zerodegree_num==0)
  {
    flag=0;
    return;
  }
  if(zerodegree_num>1)zeroflag=1; 
  for(i=1;i<=temp_lett_num;i++)
  {
    j=0;
	u=1;
	while(into[u]!=0)
	{

	  if(into[u]==-1)j++;
	  u++;
	  if(j>temp_lett_num||u>lett_num)
	  {
		flag=0;
		return;
	  }
	}
	sans[count++]=u+64;
	into[u]=-1;
	if(count==lett_num+1&&zerodegree_num==1)
		return ;
	for(int k=1;k<=edge_num;k++)
	{
	   if(edge[k].l==u)
		into[edge[k].r]--;
	}
	if(!zeroflag)
	{
	zerodegree_num=0;
	for(int t=1;t<=lett_num;t++)
      if(into[t]==0)	
       zerodegree_num++;
	  if(zerodegree_num>1)
		  zeroflag=1;
	}  
  }
  if((count<lett_num+1||zerodegree_num>1)&&(edge_num==all_edge_num))
  {
	  
	  flag=-1;return;
  }
  flag=-2;
  return ;
}
int main()
{
	int n,m,max1,max2,signal,conflict;
	int i;
	char a,b,c;
	while(cin>>n>>m)
	{
	  if(n==0&&m==0)return 0;
	  lett_num=n;
	  all_edge_num=m;
	  conflict=0;
	  max2=0;
	  signal=0;
	  memset(relate,0,sizeof(relate));
	  for(i=1;i<=m;i++)
	  {
	    cin>>a>>c>>b;
		edge[i].l=a-64;
		edge[i].r=b-64;
		max1=(edge[i].l>edge[i].r)?edge[i].l:edge[i].r;
		if(max1>n&&!signal)
		{
		  conflict=1;
		  signal=1;
		  rela_num=i;
		}
	  }
	  if(conflict)
	  {
		cout<<"Inconsistency found after "<<rela_num<<" relations."<<endl;
		continue;
	  }
	  for(i=1;i<=m;i++)
	  {
		relate[edge[i].l][edge[i].r]=1;
		max1=(edge[i].l>edge[i].r)?edge[i].l:edge[i].r;
		if(max1>max2)
		max2=max1;
		edge_num=i;
		rela_num=i;
	    Topo_Sort();
	    if(flag==1)
	    {
		  cout<<"Sorted sequence determined after "<<rela_num<<" relations: ";
		  for(int t=1;t<=n;t++)
		  cout<<sans[t];
          cout<<"."<<endl;
          break;		  
	    }
	    if(flag==0)
		{
			cout<<"Inconsistency found after "<<rela_num<<" relations."<<endl;
			break;
		}
	    if(flag==-1)
		{
		  cout<<"Sorted sequence cannot be determined."<<endl;
		  break;
		}
		if(i==m&&max2<n)
		{
			
		  cout<<"Sorted sequence cannot be determined."<<endl;
		  break;
		}
	  }
	  
	}
  return 0;
}




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值