POJ 1094 (传递闭包 + 拓扑排序)
题目大意:有 1 ~ N 个大写字母,且从 A 开始依次 N 个。再给你 M 个小于的关系,比如 A < B ,让你判断三种可能:
1、在第 i 个关系罗列之后,是否可以满足使得这 N 个字母能递增关系。
2、在第 i 个罗列之后,是否会出现矛盾,例如 A > B,而在第 i 个状态出现后,B > A ,故矛盾。
3、如果 M 个条件罗列完后都没有出现矛盾,且还无法判断 N 个字母的排列顺序,则输出 Sorted sequence cannot be determined.
在前两种情况中,输出最先满足的 i ,也就是说,按 m 个状态的顺序,满足任意一个条件后,其他条件都不用再判断。
思路与分析:
对于 A < B,我们建一个 A --> B 的有向图。
按 M 个状态的顺序,每次得到 A < B ,标记 a[A][B] 为 true,表示 A 能到达 B ,然后全图跑一遍 floyd 传递闭包,判断在第 i 个状态时,是否满足前两种情况。
1、在三层循环传递闭包结束后,判断图中任意两点间是否存在 A > B 且 B < A 的这种矛盾关系,即判断全图两点是否会有 a[i][j] = true 且 a[j][i] = true ,有的话,则判断为第二种情况,标记或输出当前 i 。
2、还需要判断的是,如果 a[i][j]==0 且 a[j][i]==0 ,则说明此时 i 与 j 点之间没有任何小于或大于关系,故在当前状态时,还未能判断出 N 个字母的关系。
可以先用数组存 M 个状态,或者是边输入边判断。但一定要注意的是,如果 floyd 判断为 false (即上一段中的两种情况),则还需要再判断任意两点 i j ,是否为上文中的第一种情况(即 a[i][j]==a[j][i]==true),是的话,则说明为题目所描述的第二种情况。
边输入边判断:
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#define inf 0x3f3f3f3f
#define maxn 100
using namespace std;
int n,m,cnt,b,w,res;
int head[maxn],in[maxn];
bool a[maxn][maxn];
char c[maxn];
struct Edge
{
int to;
int next;
}edge[maxn*maxn*];
inline void add(int u,int v)
{
edge[++cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt;
return;
}
inline bool floyd(int C)
{
for(int k=;k<=n;k++){
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(a[i][k]&&a[k][j]) a[i][j]=true;
}
}
}
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(i==j) continue;
if((a[i][j]&&a[j][i])){
b=C;
return false;
}
if(a[i][j]==&&a[j][i]==) return false;
}
}
return true;
}
void solve()
{
queue<int> q;
while(!q.empty()) q.pop();
for(int i=;i<=n;i++) {if(!in[i]) q.push(i);}
int tot=;
while(!q.empty())
{
int x=q.front();
q.pop();
c[tot++]=(char)(x+'A'-);
for(int i=head[x];i;i=edge[i].next){
int v=edge[i].to;
in[v]--;
if(!in[v]) q.push(v);
}
}
c[tot]='\0';
return;
}
void init()
{
b=cnt=w=res=;
memset(c,,sizeof(c));
for(int i=;i<=n;i++) {
head[i]=in[i]=;
for(int j=;j<=n;j++){
a[i][j]=false;
}
}
}
int main()
{
//freopen("test.in","r",stdin);
while(~scanf("%d%d",&n,&m)){
if(n==&&m==) break;
init();
char s[];
for(int i=;i<=m;i++){
scanf("%s",s);
if(w||b>=inf) continue;
int A=s[]-'A'+,B=s[]-'A'+;
a[A][B]=true;
add(A,B),in[B]++;
if(floyd(inf)){
w=;
if(!b) b=i;
continue;
}
else{//可以不需要再进行一遍判断,只需要 floyd 保存 b 之后,最后返回即可。因为可能会先被 a[i][j]==a[j][i]==0 先返回而 b 未被赋值为 inf
for(int k=;k<=n;k++){
for(int j=;j<=n;j++){
if(k==j) continue;
if(a[k][j]&&a[j][k]) {res=i;b=inf;}
}
}
}
}
if(w){
solve();
printf("Sorted sequence determined after %d relations: %s.\n", b,c);
}
else{
if(b){printf("Inconsistency found after %d relations.\n", res);}
else printf("Sorted sequence cannot be determined.\n");
}
}
}
存数组再遍历 M 个状态:
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#define inf 0x3f3f3f3f
#define maxn 30
using namespace std;
int n,m,cnt,b,w;
int head[maxn],in[maxn];
bool a[maxn][maxn];
char c[maxn],s[][];
struct Edge
{
int to;
int next;
}edge[maxn*maxn*];
inline void add(int u,int v)
{
edge[++cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt;
return;
}
inline bool floyd(int C)
{
for(int k=;k<=n;k++){
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(a[i][k]&&a[k][j]) a[i][j]=true;
}
}
}
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
if(i==j) continue;
if((a[i][j]&&a[j][i])||(a[i][j]==&&a[j][i]==)) return false;
}
}
return true;
}
void solve()
{
queue<int> q;
while(!q.empty()) q.pop();
for(int i=;i<=n;i++) {if(!in[i]) q.push(i);}
int tot=;
while(!q.empty())
{
int x=q.front();
q.pop();
c[tot++]=(char)(x+'A'-);
for(int i=head[x];i;i=edge[i].next){
int v=edge[i].to;
in[v]--;
if(!in[v]) q.push(v);
}
}
c[tot]='\0';
return;
}
void init()
{
b=cnt=w=;
memset(c,,sizeof(c));
memset(s,,sizeof(s));
memset(a,,sizeof(a));
memset(head,,sizeof(head));
}
int main()
{
//freopen("test.in","r",stdin);
while(~scanf("%d%d",&n,&m)){
if(n==&&m==) break;
init();
for(int i=;i<=m;i++){
scanf("%s",s[i]);
}
for(int i=;i<=m;i++){
int A=s[i][]-'A'+,B=s[i][]-'A'+;
a[A][B]=true;
if(floyd()){
for(int j=;j<=i;j++){
A=s[j][]-'A'+,B=s[j][]-'A'+;
add(A,B),in[B]++;
}
solve();
printf("Sorted sequence determined after %d relations: %s.\n",i,c);
w=;
}
else{
for(int k=;k<=n;k++){
for(int j=;j<=n;j++){
if(k==j) continue;
if(a[k][j]&&a[j][k]){
printf("Inconsistency found after %d relations.\n", i);
w=;
break;
}
if(w) break;
}
}
}
if(w) break;
}
if(!w) printf("Sorted sequence cannot be determined.\n");
}
}
POJ 1094 (传递闭包 + 拓扑排序)的更多相关文章
- poj 1094(拓扑排序)
http://poj.org/problem?id=1094 题意:给你m个字母,有n个判断语句.求在哪个语句就可以判断出这个是不是一个环,或者在哪个语句可以判断出这些字母的排序规则,或者就是不能确定 ...
- 【POJ 1094】拓扑排序
题意 给出n,代表有以A开始的n个字母,给出它们的m个小于关系(A<B).如果前i个关系可以确定n个字母的一个顺序就输出: Sorted sequence determined after i ...
- Poj(2367),拓扑排序
题目链接:http://poj.org/problem?id=2367 题意: 知道一个数n, 然后n行,编号1到n, 每行输入几个数,该行的编号排在这几个数前面,输出一种符合要求的编号名次排序. 拓 ...
- poj 1270(dfs+拓扑排序)
题目链接:http://poj.org/problem?id=1270 思路:就是一简单的dfs+拓扑排序,然后就是按字典序输出所有的情况. http://paste.ubuntu.com/59872 ...
- poj 3683(2-sat+拓扑排序)
Priest John's Busiest Day Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 11127 Accep ...
- 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 ...
- [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(拓扑排序)
http://poj.org/problem?id=1094 原来拓扑序可以这样做,原来一直sb的用白书上说的dfs............ 拓扑序只要每次将入度为0的点加入栈,然后每次拓展维护入度即 ...
随机推荐
- URLDecoder异常Illegal hex characters in escape (%)
URLDecoder对参数进行解码时候,代码如: URLDecoder.decode(param,"utf-8"); 有时候会出现类似如下的错误: URLDecoder异常Ille ...
- 拎壶学python3-----(1)输出与字符转换
一.输入自己的名字打印 二.数字和字符串是不能相加的如下 怎么解决上边的问题呢? 如果是相加我们要把字符串转成数字类型如下 如果不想让他相加可以写成这样如下: ok,关于转换就先讲到这里
- 知识图谱辅助金融领域NLP任务
从人工智能学科诞生之初起,自然语言处理(NLP)就是人工智能核心的研究问题之一.NLP的重要性是毋庸置疑的,它能够实现以自然语言交流为特征的高级人机交互,使机器能“阅读”所有以文字形式记录的人类知识, ...
- 【Java线程与内存分析工具】VisualVM与MAT简明教程
目录 前言 VisualVM 安装与配置 本地使用 远程监控 MAT 使用场景 安装与配置 获得堆转储文件 分析堆转储文件 窥探对象内存值 堆转储文件对比分析 总结 前言 本文将简要介绍Java线程与 ...
- 3、Hibernate的多表关联
一.数据库中的表关系: 一对一关系 一个人对应一张身份证,一张身份证对应一个人,一对一关系是最好理解的一种关系,在数据库建表的时候可以将人表的主键放置与身份证表里面,也可以将身份证表的主键放置于人表里 ...
- C#判断dataGridView1 点击的是哪一列上的按钮
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) { ) { DataGr ...
- C#函数的参数传递方式1(值传递与地址传递)
using System; namespace class1 { class program { static void Main(string[] args) { //值传递引用,实际参数不会变化 ...
- shell 命名管道,进程间通信, ncat作http server
命名管道基础 命名管道也被称为FIFO文件, 在文件系统中是可见的,并且跟其它文件一样可以读写! 命名管道特点: 当写进程向管道中写数据的时候,如果没有进程读取这些数据,写进程会堵塞 当读取管道中的数 ...
- Java生鲜电商平台-电商订单系统全解析
Java生鲜电商平台-电商订单系统全解析 说明:Java生鲜电商平台-电商订单系统全解析主要讲解OMS的内容,设计,开发,架构等知识. 今天分享将会分为以下三个环节来阐述: 1.订单系统的介绍 2.订 ...
- CSS3 2D变形 transform---移动 translate(x, y), 缩放 scale(x, y), 旋转 rotate(deg), transform-origin, 倾斜 skew(deg, deg)
transform是CSS3中具有颠覆性的特征之一,可以实现元素的位移.旋转.倾斜.缩放,甚至支持矩阵方式,配合过渡和即将学习的动画知识,可以取代大量之前只能靠Flash才可以实现的效果. 变形转换 ...