实用算法实现-第 16 篇 拓扑排序

16.1    拓扑排序

拓扑排序的本质是由某集合上的一个偏序得到该集合上的一个全序。

16.1.1   实例

PKU JudgeOnline, 1094, Sorting It All Out.

16.1.2   问题描述

给出类似A<B的一系列关系,判断输入第几个关系的时候顺序排定,或者出现环,或者所有输入完成后仍没出现环或者排定顺序。

注意:当拓扑排序不唯一(当然也就不确定)的时候 还要判断是否有环。

注意:如果前几条不等式可以确定一个序列,那么后面的的都要被忽略,即使加上它们会发生矛盾。

16.1.3   输入

46

A<B

A<C

B<C

C<D

B<D

A<B

32

A<B

B<A

261

A<Z

0 0

16.1.4   输出

Sortedsequence determined after 4 relations: ABCD.

Inconsistencyfound after 2 relations.

Sortedsequence cannot be determined.

16.1.5   分析

每次得到一个关系式后,做一次推理。

如果得到关系A<B,那么更新已知所有比A的x都比B小,更新所有比B大的x都比A大。同时检查有无冲突,并且更新推理出的关系个数。

可以显然地知道如下结论:

1. 出现矛盾关系,当且仅当:出现A<A关系,或者出现A<B&&B<A关系。

2. 如果发现n*(n-1)/2个互不相同的不矛盾的关系,那么序列已确定。

3. 第i小的数比i-1个数小。

有了以上结论,问题很容易解出。

16.1.6   程序

#include <iostream>
#include <math.h>
#include <string.h>
using namespace std;
#define maxNum     26
int larger[maxNum][maxNum];
int smaller[maxNum][maxNum];
int smallerNum[maxNum];
int relationNum;
#define SMALLER    0
#define LARGER     1
int fail;
int n;
void setRelation(int small, int large){
     if((larger[large][small]== 1)||
     (smaller[small][large] == 1)||
     small == large)
     {
         fail = 1;
         return;
     }
     larger[small][large] = 1;
     smaller[large][small] = 1;
     smallerNum[large]++;;
     relationNum++;
}
void relation(int small, int large)
{
     int i;
     if(larger[small][large]!= 0)
     {
         return;
     }
     setRelation(small, large);
     for(i = 0;i < n; i++){
         if(smaller[small][i]== 1)
         {
              relation(i, large);
         }
         if(larger[large][i]== 1)
         {
              relation(small, i);
         }
     }
}
void printResult()
{
     int i, j;
     for(i = 0;i < n; i++)
     {
         for(j =0; j < n; j++){
              if(smallerNum[j]== i){
                   printf("%c", j + 'A');
              }
         }
     }
     printf(".\n");
}
int main()
{
     int m;
     int i;
     int num;
     int finish;
     char small,large;
     while(scanf("%d%d", &n, &m)){
         if(n ==0&& m == 0)
         {
              break;
         }
         memset(smaller, 0, sizeof(smaller));
         memset(larger, 0, sizeof(larger));
         memset(smallerNum, 0, sizeof(smallerNum));        
         relationNum = 0;
         fail = 0;
         finish = 0;
         num = n * (n - 1) / 2;
         for(i =1;i <= m; i++){
              scanf("\n%c<%c",&small, &large);
              //printf("%c<%c\n",small, large);
              if(fail== 0 && relationNum < num)
              {
                   relation(small - 'A', large - 'A');
                   if(fail== 1){
                       printf("Inconsistency found after %d relations.\n",i);
                   }elseif(relationNum == num){
                       printf("Sorted sequence determined after %d relations:", i);
                       printResult();
                   }
              }
         }
         if(fail== 0 && relationNum < num)
         {
              printf("Sortedsequence cannot be determined.\n");
         }
     }
}


16.2    实例

PKU JudgeOnline, 2762, Going from u to v or from v to u?.

PKU JudgeOnline, 1094, Sorting It All Out.

本文章欢迎转载,请保留原始博客链接http://blog.csdn.net/fsdev/article

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值