Floyd判联通(传递闭包)

Floyd传递闭包顾名思义就是把判最短路的代码替换成了判是否连通的代码,它可以用来判断图中两点是否连通。板子大概是这个样的:

for(int k=1; k<=n; k++){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
// 把数值计算替换成逻辑运算——就一行,非常简便
e[i][j] = e[i][j] || (e[i][k] && e[k][j]);
}
}
}

题目描述

给定 n个变量和 m个不等式。其中 n小于等于 26,变量分别用前 n的大写英文字母表示。

不等式之间具有传递性,即若 A>B 且 B>C,则 A>C。

请从前往后遍历每对关系,每次遍历时判断:

  • 如果能够确定全部关系且无矛盾,则结束循环,输出确定的次序;
  • 如果发生矛盾,则结束循环,输出有矛盾;
  • 如果循环结束时没有发生上述两种情况,则输出无定解。

    输入格式

    输入包含多组测试数据。

每组测试数据,第一行包含两个整数 n和 m。

接下来 m行,每行包含一个不等式,不等式全部为小于关系。

当输入一行 0 0 时,表示输入终止。

输出格式

每组数据输出一个占一行的结果。

结果可能为下列三种之一:

  1. 如果可以确定两两之间的关系,则输出 "Sorted sequence determined after t relations: yyy...y.",其中't'指迭代次数,'yyy...y'是指升序排列的所有变量。
  2. 如果有矛盾,则输出: "Inconsistency found after t relations.",其中't'指迭代次数。
  3. 如果没有矛盾,且不能确定两两之间的关系,则输出 "Sorted sequence cannot be determined."。

那么我们可以分析题目:题目说要“从前往后遍历每对关系” 那么就不是一次性导入所有数据了,而是每输入一个就计算一遍。

graph TB
Begin(开始) --> A[输入不等式]
A -->E{是否存在矛盾}
E -->|存在|B[输出矛盾信息]
E -->|不存在|C
C{是否能确定两两关系}
C -->|能确定|D[输出升序排列]
C -->|不能确定|A
F{全部不等式输入完成且未发生以上情况} -->G[输出]
A -->F

那么怎么判断是否存在矛盾呢?想想看,不就是既有\(A>B\) 又有\(B>A\)吗。那么就可以在floyd的同时加入判断。

for(int k=1; k<=n; k++){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
e[i][j] = e[i][j] || (e[i][k] && e[k][j]);
// 注意要i!=j
// 如果e[i][j]和e[j][i]都联通肯定存在矛盾
if(e[i][j] && e[j][i] && i!=j){
data = 0;
}
}
}
}

那怎么判断能否确定两两关系呢?那就是在没有矛盾的前提下,两两首尾相连。如果存在两个点没有首尾相连的情况,那肯定不行的。我这里把判断它的代码单独拿了出来放在一个函数里,因为如果在floyd中写的话它是会变化的,可能在某次循环时它不连通,但循环几次后它又联通了。所以还不如拿出去.

bool check(){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(!e[i][j] && !e[j][i] && i!=j) return 0;
}
}
return 1;
}

可以判断两两关系了,那怎么打印出次序呢?我在某个大佬那里受到启发——观察矩阵。试想一下,如果\(A<B<C<D\),那么A联通的点有3个,B联通的点有2个,C联通的点有…… 也就是这个样子的:

A[1][n] 0 1 1 1
B[2][n] 0 0 1 1
C[3][n] 0 0 0 1
D[4][n] 0 0 0 0

那么就只用依次取出“1”最多的打印出来就好。

inline void out(){
// #define p pair<int, char>
priority_queue<p, vector<p>, less<p> > q;
int t;
for(int i=1; i<=n; i++){
t = 0;
for(int j=1; j<=n; j++){
if(i != j) t += e[i][j];
}
q.push( (p){t, i-1+'A'} );
}
while(!q.empty()){
printf("%c",q.top().second);
q.pop();
}
printf(".\n");
}

这道题个人感觉非常nice,他开拓了我们的新思路:观察矩阵(找规律)。好了,以上是我的全部理解。博客freshman,如有错误,还请指点!

AC代码:仅供参考

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define p pair<int, char>
int n,m,data;
bool e[27][27],node[27];
string s;
inline void floyd(){
for(int k=1; k<=n; k++){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
e[i][j] = e[i][j] || (e[i][k] && e[k][j]);
if(e[i][j] && e[j][i] && i!=j){
data = 0;
}
}
}
}
}
bool check(){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(!e[i][j] && !e[j][i] && i!=j) return 0;
}
}
return 1;
}
inline void out(){
priority_queue<p, vector<p>, less<p> > q;
int t;
for(int i=1; i<=n; i++){
t = 0;
for(int j=1; j<=n; j++){
if(i != j) t += e[i][j];
}
q.push( (p){t, i-1+'A'} );
}
while(!q.empty()){
printf("%c",q.top().second);
q.pop();
}
printf(".\n");
}
int main(){
while(scanf("%d%d",&n,&m) && n){
memset(e, 0, sizeof(e));
memset(node, 0, sizeof(node));
data = 1;
for(int i=1; i<=m; i++){
cin>>s;
e[s[0]-'A'+1][s[2]-'A'+1] = 1;
node[s[0]-'A'+1] = node[s[2]-'A'+1] = 1;
if(data == 1){
floyd();
if(data == 0){
printf("Inconsistency found after %d relations.\n",i);
//break;
}
else if(check()){
printf("Sorted sequence determined after %d relations: ",i);
out();
data = 2;
//break;
}
}
}
if(data == 1){
printf("Sorted sequence cannot be determined.\n");
}
}
}

Floyd判联通(传递闭包) & poj1049 sorting it all out的更多相关文章

  1. UVA - 247 Calling Circles Floyd判圈

    思路:利用的Floyd判圈,如果i能到j,j也能到i说明i和j在同一个圈里.每个人的名字可用map编号.最后DFS打印答案即可. AC代码 #include <cstdio> #inclu ...

  2. UVa11549计算器谜题[floyd判圈]

    题意: 有个老式计算器,每次只能记住一个数字的前n位.现在输入一个整数k,然后反复平方,一直做下去,能得到的最大数是多少.例如,n=1,k=6,那么一次显示:6,3,9,1... 白书上的题 set, ...

  3. SGU 455 Sequence analysis(Cycle detection,floyd判圈算法)

    题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=455 Due to the slow 'mod' and 'div' operati ...

  4. UVa 1594 (Floyd判圈) Ducci Sequence

    大白书上P42那个计算器的题目就用到了这个办法,Floyd判圈法. 当然,用STL里的map也是可以的. #include <cstdio> #include <cmath> ...

  5. UVA 11549 CALCULATOR CONUNDRUM(Floyd判圈算法)

    CALCULATOR CONUNDRUM   Alice got a hold of an old calculator that can display n digits. She was bore ...

  6. uva11549 Floyd判圈法

    题意: 给两个数n, k,每次将k平方取k的前n位,问所有出现过的数的最大值 原来这就是floyd判圈法.. #include<cstdio> #include<cstdlib> ...

  7. UVA 11549 Calculator Conundrum (Floyd判圈算法)

    题意:有个老式计算器,每次只能记住一个数字的前n位.现在输入一个整数k,然后反复平方,一直做下去,能得到的最大数是多少.例如,n=1,k=6,那么一次显示:6,3,9,1... 思路:这个题一定会出现 ...

  8. leetcode202(Floyd判圈算法(龟兔赛跑算法))

    Write an algorithm to determine if a number is "happy". 写出一个算法确定一个数是不是快乐数. A happy number ...

  9. Floyd判圈算法

    Floyd判圈算法 leetcode 上 编号为202 的happy number 问题,有点意思.happy number 的定义为: A happy number is a number defi ...

  10. Codeforces Gym 101252D&&floyd判圈算法学习笔记

    一句话题意:x0=1,xi+1=(Axi+xi%B)%C,如果x序列中存在最早的两个相同的元素,输出第二次出现的位置,若在2e7内无解则输出-1. 题解:都不到100天就AFO了才来学这floyd判圈 ...

随机推荐

  1. 如何应用 matrix3d 映射变幻

    如何应用 matrix3d 映射变幻 先上 demo 记得是在 2015 看到过的一个 html5 演示效果, 很惊艳 当时没明白如何实现,现在我会了,做一个类似的: 又弄了一个拖动的 demo 我数 ...

  2. EasyExcel 无法读取图片?用poi写了一个工具类

    在平时的开发中,经常要开发 Excel 的导入导出功能.一般使用 poi 或者 EasyExcel 开发,使用 poi 做 excel 比较复杂,大部分开发都会使用 EasyExcel 因为一行代码就 ...

  3. P8594 「KDOI-02」一个仇的复

    我会组合数! 首先发现同一列只有被不同的横块填或被一个相同的竖块填,且用竖块填完1列之后,会分成两个封闭的长方形,而长方形内部则用横块来填充. 先考虑一个子问题,某个 \(2 \times n\) 长 ...

  4. nginx 反向代理(proxy)与负载均衡(upstream)应用实践

    集群介绍 集群就是指一组(若干个)相互独立的计算机,利用高速通信网络组成的一个较大的计算机服务系统,每个集群节点(即集群中的每台计算机)都是运行各自服务的独立服务器.这些服务器之间可以彼此通信,协同向 ...

  5. .NET 认识日志系统-2

    .NET 日志系统2 上一篇文章是将日志打印到控制台,这篇文章将日志写入到文本文件中. 文本日志一般按照日期区分 如何避免文本日志把磁盘撑爆? 限制日志总个数或者总大小 如何避免一个日志文件太大? 限 ...

  6. 张高兴的 MicroPython 入门指南:(一)环境配置、Blink、部署

    目录 什么是 MicroPython 环境配置 硬件部分 软件部分 Hello World! Blink Pico 的引脚 常见电子元件 面包板 跳线 开关 发光二极管 电阻 使你的 Pico 闪烁 ...

  7. 【论文阅读】VDBFusion: Flexible and Efficient TSDF Integration of Range Sensor Data

    Type: Sensors Year: 2022 tag: Mapping 组织: Bonn 参考与前言 论文链接:https://www.ncbi.nlm.nih.gov/pmc/articles/ ...

  8. SpringBoot+mail 轻松实现各类邮件自动推送

    一.简介 在实际的项目开发过程中,经常需要用到邮件通知功能.例如,通过邮箱注册,邮箱找回密码,邮箱推送报表等等,实际的应用场景非常的多. 早期的时候,为了能实现邮件的自动发送功能,通常会使用 Java ...

  9. Linux 应用案例开发手册——基于Zynq-7010/20工业开发板

    目 录 1 开发案例说明 4 2 Linux 常用开发案例 4 2.1 tl_led_flash 案例 4 2.2 tl_key_test 案例 7 2.3 tl_can_echo 案例 11 2.4 ...

  10. TLScanary:Pwn中的利器

    TLScanary:Pwn中的利器 引言:什么是TLScanary?   在二进制漏洞利用(Pwn)领域,攻击者面临着层层防护措施的挑战.在安全竞赛(如CTF)和实际漏洞利用中,TLS(线程本地存储) ...