[ACM_模拟] POJ 1094 Sorting It All Out (拓扑排序+Floyd算法 判断关系是否矛盾或统一)

简介:


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.

Source

 
题目大意 :给你一些大写字母间的大小排序关系,判断以下3中情况:1 能唯一确定它们的排列顺序,2 所给关系是矛盾的,3 到最后也不能确定它们之间的关系。

解题思路:a、出现矛盾也就是在比较大小关系的过程中出现环,可以通过Floyd算法由邻接矩阵求出可达矩阵,再判断是否存在map[i][i]=1的情况

              b、如果没有环且每个点的出度+入度==n-1,则表明字母之间两两关系确定,构成唯一的一个序列,存在答案,否则不存在。

              c、当答案存在时,利用拓扑排序确定各点顺序。

相关知识:a、Floyd算法:Floyd-Warshall算法,简称Floyd算法,用于求解任意两点间的最短距离,时间复杂度为O(n^3)。其一般形式为:

复制代码
1 void Floyd(){
2      for(int k=1;k<=n;k++)
3          for(int i=1;i<=n;i++)
4              for(int j=1;j<=n;j++)
5                  if(dist[i][k]+dist[k][j]<dist[i][j])
6                      dist[i][j]=dist[i][k]+dist[k][j];
7 }
复制代码

在调用它之前只需做一些简单的初始化:dist[i][i]=0,其他dist为INF。注意这里存在一个潜在问题:当INF定义太大,加法dist[i][k]+dist[k][j]可能会溢出!但如果INF太小,可能会是长度为INF的边真的变成最短路的一部分。因此INF不能太大也不能太小,要先估算一下!如果坚持认为不应该允许INF和其他值相加,就需要把代码改成:

复制代码
1 void Floyd(){
2      for(int k=1;k<=n;k++)
3          for(int i=1;i<=n;i++)
4              for(int j=1;j<=n;j++)
5                  if(dist[i][k]<INF && dist[k][j]<INF && dist[i][k]+dist[k][j]<dist[i][j])
6                      dist[i][j]=dist[i][k]+dist[k][j];
7 }
复制代码

此外本题用到了有向图的传递闭包:在有向图中,有时不必关心路径的长度,而只关心两点是否有通路,则可以用1、0分别表示“连通”和“不连通”。这样除了预处理需要做少许修改外,主算法只需:

复制代码
1 void Floyd(){
2      for(int k=1;k<=n;k++)
3          for(int i=1;i<=n;i++)
4              for(int j=1;j<=n;j++)
5                  if(dist[i][k] && dist[k][j])
6                      dist[i][j]=1;
7 }
复制代码

b、拓扑排序:拓扑排序是对有向无环图(DAG图)的一种排序。表示了顶点按边的方向出现的先后顺序。如果有环,则无法表示两个顶点的先后顺序。

                   在现实生活中,也会有不少应用例子,比如学校课程布置图,要先修完一些基础课,才可以继续修专业课。

                   有向图可以拓扑排序的条件是:图中没有环。

                   具体方法:
                   ⑴ 从图中选择一个入度为0的点加入拓扑序列。
                   ⑵ 从图中删除该结点以及它的所有出边(即与之相邻点入度减1)。

                   反复执行这两个步骤,直到所有结点都已经进入拓扑序列。

相关链接:Folyd算法详解 http://www.cppblog.com/wing/archive/2011/03/10/141511.html

      如何理解拓扑排序算法 http://www.cnblogs.com/shanyou/archive/2006/11/16/562861.html

      拓扑排序-离散数学-详解 http://sjjg.js.zwu.edu.cn/SFXX/tu/tu5.6.1.html

AC代码

复制代码
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string.h>
 4 #include<string>
 5 #include<stack>
 6 using namespace std;
 7 
 8 #define maxn 30
 9 int n,m;
10 bool map[maxn][maxn],visit[maxn];
11 int indegree[maxn],outdegree[maxn];
12 char str[maxn],ch[maxn];
13 
14 bool Floyd(){
15     for(int i=0;i<n;i++)//Floyd对邻接矩阵的运算求可达矩阵
16         for(int j=0;j<n;j++)
17             for(int k=0;k<n;k++)
18                 if(map[j][i] && map[i][k])
19                     map[j][k]=1;
20     for(int l=0;l<n;l++)//判断是否成环
21         if(map[l][l])
22             return 0;
23     return 1;
24 }//Floyd算法对0-1邻接矩阵判断是否有环:map[i][i]=1
25 
26 bool only_sure(){
27     memset(indegree,0,sizeof(indegree));
28     memset(outdegree,0,sizeof(outdegree));
29     for(int i=0;i<n;i++)//计算出度和入度
30         for(int j=0;j<n;j++)
31             if(map[i][j])
32                 indegree[j]++,outdegree[i]++;
33     for(int k=0;k<n;k++)//所有点出度入度之和均为n-1则说明所有关系确定
34         if(indegree[k]+outdegree[k]!=n-1)
35             return 0;
36     return 1;
37 }
38 
39 //拓扑排序:从图中选择一个入度为0的点加入拓扑序列
40 //         从图中删除该结点以及它的所有出边(即与之相邻点入度减1)
41 void toplogical_sort(){
42     stack<int> Q;
43     int id=0;
44     for(int i=0;i<n;i++)
45         if(indegree[i]==0){
46             Q.push(i);
47             break;
48         }
49     memset(visit,0,sizeof(visit));
50     while(!Q.empty()){
51         int cur=Q.top();Q.pop();
52         visit[cur]=true;
53         str[id++]=cur+'A';
54         for(int j=0;j<n;j++){
55             if(!visit[j] && map[cur][j])indegree[j]--;//将所有子节点的入度-1
56             if(!visit[j] && indegree[j]==0)Q.push(j);
57         }    
58     }
59     str[id]='\0';
60 }
61 
62 int main(){
63     while(cin>>n>>m){
64         if(n==0 && m==0)break;
65         memset(map,0,sizeof(map));
66         int flag1=0;//标记矛盾出现时的步数
67         int flag2=0;//标记关系确认时的步数
68         for(int i=1;i<=m;i++){//边输入边检测
69             cin>>ch;
70             map[ch[0]-'A'][ch[2]-'A']=1;
71             if(flag1 ||flag2)continue;
72             else if(!Floyd())flag1=i;
73             else if(only_sure()){
74                 toplogical_sort ();
75                 flag2=i;
76             }
77         }
78         if (flag1) printf("Inconsistency found after %d relations.\n",flag1);
79         else if (flag2) printf("Sorted sequence determined after %d relations: %s.\n",flag2,str);
80         else printf("Sorted sequence cannot be determined.\n");
81     }return 0;
82 }
复制代码

 




本文转自beautifulzzzz博客园博客,原文链接:http://www.cnblogs.com/zjutlitao/p/3554256.html,如需转载请自行联系原作者

相关文章
|
1月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
70 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
13天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
56 8
|
13天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
45 7
|
1月前
|
搜索推荐 Shell
解析排序算法:十大排序方法的工作原理与性能比较
解析排序算法:十大排序方法的工作原理与性能比较
51 9
|
1月前
|
算法 搜索推荐 Java
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
基数排序是一种稳定的排序算法,通过将数字按位数切割并分配到不同的桶中,以空间换时间的方式实现快速排序,但占用内存较大,不适合含有负数的数组。
24 0
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
|
1月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
31 0
|
1月前
|
存储 算法 搜索推荐
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
72 0
|
1月前
|
存储 算法 C++
弗洛伊德(Floyd)算法(C/C++)
弗洛伊德(Floyd)算法(C/C++)
|
28天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
13天前
|
算法 数据挖掘 数据安全/隐私保护
基于FCM模糊聚类算法的图像分割matlab仿真
本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。
下一篇
无影云桌面