nyoj349 poj1094 Sorting It All Out(拓扑排序)
nyoj349 http://acm.nyist.net/JudgeOnline/problem.php?pid=349
poj1094 http://poj.org/problem?id=1094
这两个题是一样的,不过在poj上A了才算真的过,ny上数据有一点弱。
题目大意输入n,m。 一共有n个字母(从A开始), m行语句每个语句“x﹤y”,说明x,y之间的偏序关系。让你判断是否可以通过这些关系得到一个唯一的升序序列,若能则输出这个序列并指出通过前多少条语句得出的,如果n个字母间存在矛盾,输出相应语句并指出那条语句开始出现矛盾的。如果没有唯一序列又不存在矛盾就输出想应信息。
分析:
所用算法拓扑排序:使有向图G的每一条边(u,v)对应的u都排在v的前面。不难发现如果图中存在又向环,则不存在拓扑排序。拓扑排序答案可能有多个(例如:a﹤b; c﹤b; d﹤c; 排序可为adcb或dacb),但此题中要求排序唯一。
首先我们可以把每组小于关系看成是一个又向边,这样我们还会得到一个又向图,我们所要做的就是把图中所有点排序,因为需要知道在哪出现矛盾,在哪可以得到唯一排序的,那么我们就每输入一个边(小于关系)就更新一次图,做一回拓扑排序,看是否能得到唯一排序、有矛盾。如果所有边都结束了还没有矛盾,那就看看排序是否唯一。
在排序的时候我们需要记录每个点u所排的位置(小的排在前面),已知的由u为出发点的边可能有多个(也就是已给出多个“u﹤xi”的偏序关系),那么u点所拍的位置就是所有xi中的最小值-1。
#include<iostream>
#include<cstdio>
#include<string.h>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
//v[i]标记第i个字母是否dfs过, sum[i]存储排在第i位的字母有几个(用来判断排序是否唯一)
int n, m, v[], a[], sum[], k[];
vector<int> vec[];
struct egde
{
int x, y;
}e[];
int dfs(int x)
{
int flag = ;
v[x] = -;//正在搜索的点标记为-1
int mi = n+;
for(int i = ; i < vec[x].size(); i++)
{
flag = ;
int y = vec[x][i];
if(v[y] < ) return ;
else if(v[y] == )
{
if(dfs(y) == )
return ;
else
mi = min(mi, a[y]);
}
mi = min(mi, a[y]);
}
v[x] = ;//搜索过的点标记为1
//a[x]记录字母x排在第几位
if(flag == )//flag=1说明有已知比他大的点, x就排在 所有比它大的点的最小位置 的前面
a[x] = mi - ;
else a[x] = n;//flag= 0,说明x是已知最大的点之一,排在最后一位n位
return ;
}
int topu()
{
memset(v, , sizeof(v));
for(int i = ; i <= n; i++) a[i] = n+;//初始化所有点的排序位置为n+2;
for(int i = ; i <= n; i++)
{
if(v[i] == && vec[i].size() != )
{
int tem = dfs(i);
if(tem == ) return ;
}
}
return ;
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF && n && m)
{
for(int i = ; i <= m; i++)
{
char a, b, c;
int tem;
cin >> a >> c >> b;
tem = a - 'A' + ; e[i].x = tem;//e[i]存储第i条边的两个点
tem = b - 'A' + ; e[i].y = tem;
}
int error = -;
int flag;//标记排序是否为为一
for(int i = ; i <= n; i++) {vec[i].clear();}
for(int i = ; i <= m; i++)
{
flag = ;
vec[e[i].x].push_back(e[i].y);//不断加入边, 每次加边都跟新存出边的vec;
error = topu();//每次加边都进行一次拓扑排序, 返回值=0时,存在矛盾, 返回值=1时没有矛盾
if(error == )//error = 0, 则有矛盾
{
printf("Inconsistency found after %d relations.\n", i);
break;
}
else if(error == )
{
memset(sum, , sizeof(sum));
flag = ;
for(int i = ; i <= n; i++)
{
if(a[i] == n + )//当字母i排在第n+2位时,说明字母i没由与它连接的边,
{
flag = ;continue;
}
sum[a[i]]++;//sum[i]存储排在第i位的字母有几个(用来判断排序是否唯一)
k[a[i]] = i;//k[i]记录排在第i位的字母
if(sum[a[i]] > ){flag = ; break;}//如果排在同一位置的字母不止一个,则有矛盾
}
if(flag == )//若所有点都有与之连接的边,并且字母所拍的位置不重复则说明排序唯一
{
printf("Sorted sequence determined after %d relations: ", i);
for(int i = ; i <= n; i++)
printf("%c", k[i] + 'A' - );
printf(".\n");
break;
}
}
}
if(flag == )//若不存在矛盾, 但是字母的所排位置有重复,则说明排序不唯一
printf("Sorted sequence cannot be determined.\n");
}
return ;
}
nyoj349 poj1094 Sorting It All Out(拓扑排序)的更多相关文章
- [poj1094]Sorting It All Out_拓扑排序
Sorting It All Out poj-1094 题目大意:给出一些字符串之间的大小关系,问能否得到一个唯一的字符串序列,满足权值随下标递增. 注释:最多26个字母,均为大写. 想法:显然,很容 ...
- POJ1094 Sorting It All Out —— 拓扑排序
题目链接:http://poj.org/problem?id=1094 Sorting It All Out Time Limit: 1000MS Memory Limit: 10000K Tot ...
- ACM: poj 1094 Sorting It All Out - 拓扑排序
poj 1094 Sorting It All Out Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%lld & ...
- poj 1094 Sorting It All Out (拓扑排序)
http://poj.org/problem?id=1094 Sorting It All Out Time Limit: 1000MS Memory Limit: 10000K Total Su ...
- POJ- 1094 Sorting It All Out---拓扑排序是否唯一的判断
题目链接: https://vjudge.net/problem/POJ-1094 题目大意: 该题题意明确,就是给定一组字母的大小关系判断他们是否能组成唯一的拓扑序列.是典型的拓扑排序,但输出格式上 ...
- POJ1094 Sorting It All Out LUOGU 排序
Sorting It All Out Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 40012 Accepted ...
- POJ 1094:Sorting It All Out拓扑排序之我在这里挖了一个大大的坑
Sorting It All Out Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 29984 Accepted: 10 ...
- [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 ...
- POJ 1094 Sorting It All Out (拓扑排序) - from lanshui_Yang
Description An ascending sorted sequence of distinct values is one in which some form of a less-than ...
随机推荐
- HDU 3416 Marriage Match IV dij+dinic
题意:给你n个点,m条边的图(有向图,记住一定是有向图),给定起点和终点,问你从起点到终点有几条不同的最短路 分析:不同的最短路,即一条边也不能相同,然后刚开始我的想法是找到一条删一条,然后光荣TLE ...
- Git branch (分支学习)
以前总结的一些git操作,分享在这里. Git 保存的不是文件差异或者变化量,而只是一系列文件快照. - 列出当前所有分支 git branch <--merge> | <--n ...
- rmi 与 远程代理复习
ref:http://blog.csdn.net/pipisky2006/article/details/7296592 RMI: 远程方法调用,简单来说以前是调用本地对象的方法,现在如果对象在另外一 ...
- Hadoop学习记录(5)|集群搭建|节点动态添加删除
集群概念 计算机集群是一种计算机系统,通过一组松散继承的计算机软件或硬件连接连接起来高度紧密地协作完成计算工作. 集群系统中的单个计算机通常称为节点,通过局域网连接. 集群特点: 1.效率高,通过多态 ...
- 第4章 类型基础 -- 4.1 所有类型都从System.Object派生
4.1 所有类型都从System.Object派生 “运行时”要求每个类型最终都从System.Object类型派生. 由于所有类型最终都从System.Object派生,所以每个类型的每个对象都保证 ...
- Worker工作者进程
- 问题-[DelphiXE2]提示第三控件不存在
问题情况:在DelphiXE2启动时界面显示加载了控件,并且控件的路径也放在了环境变量中,但打开程序报第三控件不存在. 问题原因:是没有选择要加载的控件. 问题处理:点击Component->I ...
- Mozilla NPAPI开发示例之一(VS2012 + Win7(64位))
入门级的NPAPI开发. NPAPI & NPRuntime 简介 Netscape Plugin Application Programming Interface (NPAPI) NPAP ...
- (一)Redis初学教程之安装篇
1.下载windows下Redis服务安装程序(有32位的和64位的,识操作系统安装) 下载地址:https://github.com/dmajkic/redis/downloads 2.安装教程(详 ...
- 理解C++中函数的返回
连续几年的C++程序设计课教学中,学生中总有人要求为他们单独解释函数的返回(return)究竟是什么意思.各种书中都会详讲返回值的问题,而学生们掌握的难点却是在返回至何处执行.本文试图通过对一般函数及 ...