luogu1347 排序 (拓扑排序)

题目描述

一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D。在这道题中,我们将给你一系列形如A<B的关系,并要求你判断是否能够根据这些关系确定这个数列的顺序。

输入输出格式

输入格式:

第一行有两个整数n,m,n表示需要排序的元素数量,2<=n<=26,第1到n个元素将用大写的A,B,C,D....表示。m表示将给出的形如A<B的关系的数量。

接下来有m行,每行有3个字符,分别为一个大写字母,一个<符号,一个大写字母,表示两个元素之间的关系。

输出格式:

若根据前x个关系即可确定这n个元素的顺序yyy..y(如ABC),输出

Sorted sequence determined after xxx relations: yyy...y.

若根据前x个关系即发现存在矛盾(如A<B,B<C,C<A),输出

Inconsistency found after 2 relations.

若根据这m个关系无法确定这n个元素的顺序,输出

Sorted sequence cannot be determined.

(提示:确定n个元素的顺序后即可结束程序,可以不用考虑确定顺序之后出现矛盾的情况)

输入输出样例

输入样例#1: 复制

1:
4 6
A<B
A<C
B<C
C<D
B<D
A<B

2:
3 2
A<B
B<A

3:
26 1
A<Z

输出样例#1: 复制

1:
Sorted sequence determined after 4 relations: ABCD.
2:
Inconsistency found after 2 relations.
3:
Sorted sequence cannot be determined.
 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 typedef long long LL;
 4 const int MAX=40;
 5 int n,m,f[MAX][MAX],du[MAX];
 6 int tot,head[MAX],adj[MAX],next[MAX];
 7 inline int read(){
 8     char c=getchar();while (c<‘A‘ || c>‘Z‘) c=getchar();return c-‘A‘+1;
 9 }
10 void addedge(int u,int v){
11     tot++,du[v]++;adj[tot]=v,next[tot]=head[u],head[u]=tot;
12 }
13 void floyd(){
14     int i,j,k;
15     for (k=1;k<=n;k++)
16         for (i=1;i<=n;i++)
17             for (j=1;j<=n;j++)
18                 f[i][j]|=f[i][k]&f[k][j];
19 }
20 void topsort(int cas){
21     int i,j,dd[MAX];
22     queue <int> q,ans;
23     for (i=1;i<=n;i++) dd[i]=du[i];
24     for (i=1;i<=n;i++) if (!dd[i]) q.push(i);
25     if (q.size()>1) return;
26     while (!q.empty()){
27         int u=q.front();q.pop();ans.push(u);
28         for (i=head[u];i;i=next[i]){
29             dd[adj[i]]--;
30             if (!dd[adj[i]]){
31                 q.push(adj[i]);
32                 if (q.size()>1) return;
33             }
34         }
35     }
36     printf("Sorted sequence determined after %d relations: ",cas);
37     while (!ans.empty()) putchar(ans.front()+‘A‘-1),ans.pop();putchar(‘.‘);
38     exit(0);
39 }
40 int main(){
41     freopen ("sort.in","r",stdin);freopen ("sort.out","w",stdout);
42     int i,j,u,v;
43     scanf("%d%d",&n,&m);
44     for (i=1;i<=m;i++){
45         u=read(),v=read();
46         if (f[v][u] || u==v) return printf("Inconsistency found after %d relations.",i),0;
47         if (!f[u][v]) f[u][v]=1,addedge(u,v);
48         floyd();topsort(i);
49     }
50     puts("Sorted sequence cannot be determined.");
51     return 0;
52 }
时间: 2024-08-30 16:03:45

luogu1347 排序 (拓扑排序)的相关文章

python 排序 拓扑排序

在计算机科学领域中,有向图的拓扑排序是其顶点的先行排序,对于每个从顶点u到顶点v的有向边uv,在排序的结果中u都在v之前. 如果图是有向无环图,则拓扑排序是可能的(为什么不说一定呢?) 任何DAG具有至少一个拓扑排序,并且这些已知算法用于在线性时间内构建任何DAG的拓扑排序 图论:是组合数学的一个分支,它和其他分支比如:群论.拓扑学.矩阵论有着密切的关系.图是图论的主要研究对象.图是由若干给定的顶点以及连接两定点的变构成的图形,这些图形通常用来描述某些事物间的某种特定关系.顶点用于代表事物,而顶

图论排序---拓扑排序

定义 对于有向无权无环图,进行拓扑排序 实现方式 Kahn算法 基于DFS的拓扑排序算法 Kahn算法 优化前时间复杂度O(\(n^{2}\)) 排序的过程 1.对于DAG,先输出没有前驱的点 2.把与前驱相关的边删除 3.继续输出没有前驱的点 4.重复前者,直到DAG为空或者没有前驱 如果我们有如下的一个有向无环图,我们需要对这个图的顶点进行拓扑排序,过程如下: 首先,我们发现V6和v1是没有前驱的,所以我们就随机选去一个输出,我们先输出V6,删除和V6有关的边,得到如下图结果: 然后,我们继

[2016-02-18][拓扑排序]

[2016-02-18][拓扑排序] 拓扑排序 思路    dfs 分析 从树的角度来看,就是不同层的节点,顺序是一定的,同层的节点,顺序是不定的, 但是拓扑排序的图不一定是树,可以有环(不能是同向的环,即1->2->3->1 这种) 为了避免漏了节点,必须枚举每一个点跑一次dfs 为了避免出现通向环的情况,必须加上标志,在每次dfs时候,标记非0值表示访问过,但是进入下一层dfs时,标记为-1,如果下层dfs访问到这个节点时的标记为-1,说明有环,出来dfs才设置为1,表示这个点后面没

数据结构:图--拓扑排序

拓扑排序 拓扑排序 在实际应用中,有向图的边可以看做是顶点之间制约关系的描述.把顶点看作是一个个任务,则对于有向边<Vi,Vj>表明任务Vj的完成需等到任务Vi完成之后,也就是说任务Vi先于任务Vj完成.对于一个有向图,找出一个顶点序列,且序列满足:若顶点Vi和Vj之间有一条边<Vi,Vj>,则在此序列中顶点Vi必在顶点Vj之前.这样的一个序列就称为有向图的拓扑序列(topological order). 步骤 从有向图中选取一个没有前驱(入度为0)的顶点输出. 删除图中所有以它为

算法-有向环和拓扑排序

有向图中包括有向无环图和有向有环图,有向图在任务调度的时候优先级限制是非常有用的,最常见的是大学的排课系统,比如说计算机操作系统的优先级高于高等数学,我们可以用图表示为计算机操作系统→高等数学,高等数学高于线性代数,如果这个时候线性代数的优先级高于计算机操作系统,那么就产生了一个有向环,无法进行排课,课程一般比较多,如果用图表示去判断是否存在环路是比较麻烦的一个事情,所以通常需要判断有向图中是否含有向环. 有向环检测 如果有向图中的某个节点可以按照路径的方向从某个节点开始并返回本身,形成了闭环可

【图论】拓扑排序应用

拓扑排序虽是一种排序,但是它跟平时所接触的sort或者qsort不同,排序的意义不同.拓扑排序针对有向无回路图(DAG)而言的,不应用与存在回路的有向图. [图论]广度优先搜索和深度优先搜索 有说到了BFS和DFS,拓扑排序是DFS的一个应用. 有向无回路图能说明事件的发生的先后的顺序.比如穿衣服,士兵排队等.一个具体的例子,有N个物体,下面给出物体的重量比较,比如(a,b)表示a比b重等等,问已给出的条件是否会矛盾?其实就是判断用所给条件所组织的一个图中是否会存在环? 在DFS中加入时间戳,完

hihoCoder#1185 : 连通性&#183;三 tarjan求强联通分量 缩点 dfs/拓扑排序求路径和最大值

题目链接: http://hihocoder.com/problemset/problem/1185# 题意: n个点,每个点有一个权值,m条有向边,从1出发,每走到一个点, 就吃掉这个点的草,当没有可以到达的草场或是能够到达的草场都已经被吃光了之后就要返回到1了.求最多可以吃掉多少草. 思路: 提示里面讲的挺好的 如果草场是一个强连通图,那么我们只要走到任意一点,就可以把其他所有的草场都走一遍,并且可以选择任意一个点作为终点.所以把强联通块缩成一个点 因为一个强连通块会被缩成一个点,那么我们可

【数据结构】拓扑排序、最短路径算法、Dijkstra算法、无环图等等

图的定义 图(graph)G = (V,E)由顶点(vertex)的集V和边(Edge)的集E组成.有时也把边称作弧(arc),如果点对(v,w)是有序的,那么图就叫做有向的图(有向图).顶点v和w邻接(adjacent)当且仅当(v,w)属于E. 如果无向图中从每一个顶点到其他每个顶点都存在一条路径,则称该无向图是连通的(connected).具有这样性质的有向图称为是强连通的(strongly connected).如果有向图不是强连通的,但它的基础图(underlying graph)(也

拓扑排序欢乐多

拓扑排序 拓扑排序 一:使用DFS实现 二:使用入度概念以及队列处理 1.使用一般队列 2.使用优先队列(这里定义越大的整数拥有越大的优先级) 一:使用DFS实现 #include <bits/stdc++.h> using namespace std; #define maxn 10000 + 10 int c[maxn],topo[maxn], k; int n, r; vector<int>G[maxn]; int dfs(int u) { c[u] = -1; for(in