P1347 排序

题目描述

一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列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:

4 6
A<B
A<C
B<C
C<D
B<D
A<B
输出样例#1:

Sorted sequence determined after 4 relations: ABCD.
输入样例#2:

3 2
A<B
B<A
输出样例#2:

Inconsistency found after 2 relations.
输入样例#3:

26 1
A<Z
输出样例#3:

Sorted sequence cannot be determined

这道题我来提供一种tarjan+拓扑排序的做法,首先我们考虑满足第二种情况的序列,如果存在矛盾,那么这个图中一定存在环,这样我们就可以用tarjan缩点判断一下是否存在环,有一点需要注意,就是如果小于号两边的数相同,那么就一定产生矛盾(非常坑)。对于第一种情况的序列,不难看出这个序列的拓扑序一定是唯一的,而且一定不存在环,也就是说每次拓扑时在栈中的元素一定只有唯一的一个,这样只需在每次拓扑开始时判断一下元素个数即可。如果第一和第二种情况均不满足,那么一定就是第三种情况咯。

最后附上代码:

 #include<iostream>
#include<string>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<stack>
#define maxn 1005
using namespace std; struct edge
{
int next;
int to;
}g[maxn<<];
int n,m,num,col,tot,cnt,pd,cnt2,cc,pd1;
int last[maxn],de[maxn],dfn[maxn],low[maxn],co[maxn],de1[maxn];
char aa[],bb[maxn];
stack<int>s;
stack<int>ss; void add(int from,int to)
{
g[++num].next=last[from];
g[num].to=to;
last[from]=num;
} void topo()
{
for(int i=;i<=n;i++)
{
if(de1[i]==)
{
ss.push(i);
}
}
while(ss.size())
{
if(ss.size()>)//如果栈中多余一个元素,说明topo序不唯一
{
pd1=;
break;
}
int u=ss.top();ss.pop();
bb[++cc]=char(u+'A'-);
for(int i=last[u];i;i=g[i].next)
{
int v=g[i].to;
de1[v]--;
if(de1[v]==)
{
ss.push(v);
}
}
}
} void tarjan(int u)
{
dfn[u]=low[u]=++tot;
s.push(u);
for(int i=last[u];i;i=g[i].next)
{
int v=g[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(!co[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u])
{
col++;cnt=;
for(;;)
{
int x=s.top();s.pop();
co[x]=col;
cnt++;
if(cnt>) pd=;//如果一个强联通分量中存在不止一个点,说明有环
if(x==u) break;
}
}
} int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%s",aa);
add(aa[]-'A'+,aa[]-'A'+);
if(aa[]-'A'+==aa[]-'A'+)
{
printf("Inconsistency found after %d relations.",i);//这里需要特判一下,不然第一个点会wa
return ;
}
de[aa[]-'A'+]++;
de1[aa[]-'A'+]=de[aa[]-'A'+];
for(int j=;j<=n;j++)
de1[j]=de[j];
tot=;col=;cc=;pd1=;
memset(co,,sizeof(co));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
while(s.size()) s.pop();
while(ss.size()) ss.pop();
for(int j=;j<=n;j++)
{
if(!dfn[j])
{
tarjan(j);//tarjan判环
}
}
if(pd==)
{
printf("Inconsistency found after %d relations.",i);
return ;
}
topo();//topo检查topo序是否唯一
if(pd1==)
{
printf("Sorted sequence determined after %d relations: ",i);
for(int j=;j<=n;j++)
{
printf("%c",bb[j]);
}
printf(".");
return ;
}
}
printf("Sorted sequence cannot be determined.");
return ;
}

P1347 排序的更多相关文章

  1. 洛谷——P1347 排序

    洛谷—— P1347 排序 题目描述 一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D.在这道题中,我们 ...

  2. P1347 排序 (拓扑排序,tarjan)

    题目 P1347 排序 解析 打开一看拓扑排序,要判环. 三种情况 有环(存在矛盾) 没环但在拓扑排序时存在有两个及以上的点入度为0(关系无法确定) 除了上两种情况(关系可确定) 本来懒了一下,直接在 ...

  3. 洛谷 P1347 排序

    题目描述 一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D.在这道题中,我们将给你一系列形如A<B ...

  4. luogu P1347 排序

    题目描述 一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D.在这道题中,我们将给你一系列形如A<B ...

  5. 洛谷P1347 排序

    这个题看到很多人写Topo排序,其实这道题第一眼看更像是一个差分约束的裸题QWQ... 令dis[x]表示x的相对大小(1是最小,n是最大),显然,对于一个关系A<B,我们有dis[A]< ...

  6. POJ1094 Sorting It All Out LUOGU 排序

        Sorting It All Out Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 40012   Accepted ...

  7. 23-25 October in 614

    Practice sort 给定一系列形如 \(A<B\) 的不等关系,判断前 \(k\) 个不等关系是否即可确定 \(n\) 个元素之间的大小顺序:如果不可确定,判断前 \(k\) 个不等关系 ...

  8. 【洛谷P1347】排序

    题目大意:给定 N 个变量和 M 个变量之间的偏序关系,问能否求出这 N 个变量之间的一个全序.若能,输出最少利用多少条已知信息即可求的结果,且输出该全序:若无解,输出到第几条已知信息可以判定无解:若 ...

  9. 题解【洛谷P1347】排序

    题目描述 一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列\(A,B,C,D\) 表示\(A<B,B<C,C<D\).在这道题中,我们将给你一系列 ...

随机推荐

  1. cocos 常用组件

    前面的话 本文将详细介绍 cocos 中的常用组件 Sprite [概述] Sprite(精灵)是 2D 游戏中最常见的显示图像的方式,在节点上添加 Sprite 组件,就可以在场景中显示项目资源中的 ...

  2. PHP——??空合并运算符和?:三元运算符

    前言 在上一篇随笔,用三元运算符简单写的一个东西,引发了对他的兴趣,所以打算研究下. PHP7的新特性: https://php.net/manual/zh/migration70.new-featu ...

  3. CBV源码分析

    1 在views中写一个类,继承View,里面写get方法,post方法 2 在路由中配置: url(r'^test/', views.Test.as_view()),实际上第二个参数位置,放的还是一 ...

  4. bzoj1444[Jsoi2009]有趣的游戏[AC自动机]

    题面 bzoj 我要向师父学习善待每一只数据结构 考虑成环,那么高斯消元 然鹅这道题太小了 所以直接转移矩阵自乘就好啦 终点不向外连边 有一条向自己的,概率为一的自环来作为结尾 对于其他店 若有边\( ...

  5. java异常和错误相关

    1.挺常见的一个问题,是个error java.lang.NoClassDefFoundError: 当目前执行的类已经编译,但是找不到它的定义时 也就是说你如果编译了一个类B,在类A中调用,编译完成 ...

  6. idea代码出现Usage of API documented as @since 1.8+ less... (Ctrl+F1)

    问题: Usage of API documented as @since 1.8+ less... (Ctrl+F1) This inspection finds all usages of met ...

  7. Linux下的sudo及配置

    sudo的常用命令 man sudoers # 参阅帮助 visudo # 编辑sudoers文件的命令 sudo -l # 查看可执行或禁止执行的命令 sudo -u user1 /bin/ls # ...

  8. [JDK8] Stream

    1 collect(toList()) collect(toList()) 方法由Stream 里的值生成一个列表,是一个及早求值操作. 2 map 如果有一个函数可以将一种类型的值转换成另外一种类型 ...

  9. 在 IDEA中运行 WordCount

    一.新建一个maven项目 二.pom.xml 中内容 <?xml version="1.0" encoding="UTF-8"?> <pro ...

  10. Eclipse——手把手教新手安装Eclipse

    一.准备工作:安装JRE和JDK. 全名分别为:Java Runtime Environmen和Java SE Development Kit,推荐直接在某度软件中心下载即可,注意区分64位和32位. ...