2016 ICPC合肥站 传递 HDU-5961(拓扑排序 / bitset / 暴力(可hack))

题目链接:HDU-5961 传递
中文题面就不解释题目意思,解释一下名词的意思
完全图:对于一个无向图 G G G 而言,设点集为 V V V,点集中任意不相同两点 u , v u, v u,v 间都有且仅有一条边叫做完全图。
竞赛图:在一个完全图的基础上给所有边定向,就变成了竞赛图。
可传递:在一个有向图中若存在边 ( a → b ) (a\rightarrow b) (ab)(代表一条由 a a a 指向 b b b 的边,下同),和 ( b → c ) (b\rightarrow c) (bc)。则一定要存在边 ( a → c ) (a\rightarrow c) (ac) 若不存在即不合法。

拓扑排序

思路

我认为的正解,很妙的反向建图的思路,一直思考暴力没往这方面想。

考虑任意图不合法的情况

  1. 有环存在同一图中: ( a → b ) ( b → c ) ( c → a ) (a\rightarrow b) (b\rightarrow c) (c\rightarrow a) (ab)(bc)(ca)
    在这里插入图片描述

  2. 存在需要满足可传递的前置情况,却少了边
    P P P 图: ( a → b ) ( b → c ) (a\rightarrow b) (b\rightarrow c) (ab)(bc) (理应要有 ( a → c ) (a\rightarrow c) (ac) 才合法,但这条边却存在与另一图中)
    Q Q Q 图: ( a → c ) / ( c → a ) (a\rightarrow c) / (c\rightarrow a) (ac)/(ca)
    在这里插入图片描述
    在这里插入图片描述

情况1:只需要对图跑一遍拓扑排序判环即可解决。
情况2:因为竞赛图是在完全图基础上定向而来,那么如果一个图P仅有 ( a → b ) ( b → c ) (a\rightarrow b) (b\rightarrow c) (ab)(bc),没有 ( a → c ) / ( c → a ) (a\rightarrow c) / (c\rightarrow a) (ac)/(ca)
不是情况1的环但也不合法, 但 ( a → c ) / ( c → a ) (a\rightarrow c) / (c\rightarrow a) (ac)/(ca) 一定会存在另一张图 Q Q Q 中。
如果 Q Q Q 图中存在的是 ( c → a ) (c \rightarrow a) (ca),那么我们如果将两个图合并起来,就会形成 ( a → b ) ( b → c ) ( c → a ) (a\rightarrow b) (b\rightarrow c) (c\rightarrow a) (ab)(bc)(ca) 的环。
如果存在的是 ( a → c ) (a \rightarrow c) (ac),那么我们将 Q Q Q 图的边反向再与图 P P P 合并那么也将构成环。

于是得出结论:将 P , Q P,Q PQ 图中任意一个反向记为 Q ′ Q' Q(不妨假设将 Q Q Q 反向)
将图 P , Q P, Q P,Q 合并拓扑排序判环,再将图 P , Q ′ P,Q' P,Q 合并拓扑排序判环 任意情况有环即不合法。

网上很多题解都仅仅是将图 Q Q Q 反向与 P P P 合并判环,而没有将原图 Q Q Q P P P 反向判环这是错误的,两者都需要才能正确判断,这里提供一个hack样例。

input:
2
3
-P-
--P
Q--
3
-PQ
--P
---

output:
N
N

代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 2023;
char mp[N][N];

int n, head[N], in[N], tot;
struct edge{
    int to, nex;
}e[N * N];

void add(int from, int to){
    in[to] ++;
    e[++ tot].to = to;
    e[tot].nex = head[from];
    head[from] = tot;
}

void build(int op){ // 建图
    tot = 0;
    for(int i = 1; i <= n; i ++) {
        in[i] = head[i] = 0;
    }
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= n; j ++){
            if(mp[i][j] == 'P') add(i, j);
            if(mp[i][j] == 'Q'){ 
                if(op == 1) add(i, j); // 正
                else add(j, i); // 反
            }
        }
    }
}

queue<int>q;
bool topsort(int op){
    build(op);
    vector<int>cnt;
    
    for(int i = 1; i <= n; i ++){
        if(!in[i]) q.push(i);
    }

    while(!q.empty()){
        int u = q.front(); q.pop();
        cnt.push_back(u);
        for(int i = head[u]; i; i = e[i].nex){
            int v = e[i].to; in[v] --;
            if(!in[v]) q.push(v);
        }
    }
    return (int)cnt.size() == n;
}

void solve(){
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++){
        scanf("%s", mp[i] + 1);
    }
    
    if(!topsort(1) || !topsort(0)) puts("N");
    else puts("T");
}

int main(){
    int t;
    scanf("%d",&t);
    while(t --){
        solve();
    }
    return 0;
}

暴力

思路

将图用邻接表存(vector / 链式前向星)对两个图分别三重for循环暴力判断。注意这种方法是可以被hack掉的,但是不知道是赛时数据弱还是怎么回事,能成功AC。
接下来给出hack样例和构造方法:其实就是让所有边都只存在一张图 P P P 中并且该图合法,任意点都指向编号大于自己的其他点,然后将数据拉满 T = 8 , n = 2000 T = 8, n = 2000 T=8,n=2000 即可。
hack样例

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 2023;
char mp[N][N];

int vis[N], n;
bool flag;
vector<int>g[2][N];

bool check(int op){
    for(int i = 1; i <= n; i ++){
        for(int j = 0; j < g[op][i].size(); j ++){
            int u = g[op][i][j];
            for(int k = 0; k < g[op][u].size(); k ++){
                int v = g[op][u][k];
                if(op == 0 && mp[i][v] != 'Q') return true;
                if(op == 1 && mp[i][v] != 'P') return true;
            }
        }
    }
    return false;
}
void solve(){
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++){
        scanf("%s", mp[i] + 1);
        g[0][i].clear();
        g[1][i].clear();
    }

    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= n; j ++){
            if(mp[i][j] == '-') continue ;
            g[mp[i][j] == 'P'][i].push_back(j);
        }
    }
    if(check(1) || check(0)) puts("N");
    else puts("T");
}

int main(){
    int t;
    scanf("%d",&t);
    while(t --){
        solve();
    }
    return 0;
}

bitset优化暴力

可以看这位老哥的 WA是一笔财富

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/17006.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

刚转岗做项目经理,无从下手,怎么办?

01 背景 最近在知乎平台看到一个问题是这么说的&#xff1a; 或许很多人都不是从工作开始就是项目专员再到项目经理这里一步一步过来&#xff0c;而是从其他岗位比如售前、销售、产品经理、程序员等转到项目经理岗位的。 那么对于这些人来说&#xff0c;做项目经理会有什么问…

Packet Tracer - 静态路由故障排除

Packet Tracer - 静态路由故障排除 地址分配表 设备 接口 IPv4 地址 子网掩码 默认网关 R1 G0/0 172.31.1.1 255.255.255.128 不适用 S0/0/0 172.31.1.194 255.255.255.252 不适用 R2 G0/0 172.31.0.1 255.255.255.0 不适用 S0/0/0 172.31.1.193 255.255…

什么是http代理504网关超时错误,要如何修复?

当你在使用 HTTP 代理时&#xff0c;有时候会遇到"504 网关超时"错误&#xff0c;这个错误看起来非常可怕&#xff0c;但实际上它并不是一个很难解决的问题。在本文中&#xff0c;我将向你介绍 504 错误的定义&#xff0c;以及为什么我们会遇到这个错误&#xff0c;同…

论文笔记——chatgpt评估+

文章目录 1. chatgpt 效果评估:Evaluating ChatGPT’s Information Extraction Capabilities: An Assessment of Performance, Explainability, Calibration, and Faithfulness文章简介文章结论 2. 事件抽取&#xff1a; OneEE: A One-Stage Framework for Fast Overlapping an…

UAD142A01 3BHE012551R0001使用以太网交叉电缆,您也可以直接连接。

​ UAD142A01 3BHE012551R0001使用以太网交叉电缆&#xff0c;您也可以直接连接。 如何将 MicroLogix PLC 连接到计算机并将程序下载到 MicroLogix 1100 MicroLogix PLC由美国罗克韦尔自动化旗下知名工业自动化厂商Allen-Bradley设计。MicroLogix 1100 主要用于小型工业。我们在…

山东专升本计算机第一章-计算机信息技术与计算机文化

计算机信息技术与计算机文化 计算机中的信息表示 数制及其转换 数制&#xff1a;用进位的原则进行计数数码&#xff1a;数制中表示基本数值大小的不同数字符号基数&#xff1a;一种数制所使用的数码个数位权&#xff1a;数码在不同位置的权值 数制的转换 • R进制转化为十进…

【五一创作】【远程工具】- Tabby 下载、安装、使用、配置【ssh/Serial】-免安装、解压即用

目录 一、Tabby 概述 二、Tabby 下载、安装 三、Tabby 的使用  &#x1f449;3.1 使用SSH协议连接Linux开发主机  &#x1f449;3.2 使用Serial(串口)协议连接开发板 一、Tabby 概述 在远程终端工具中&#xff0c;secureCrt 和 XShell 是两款比较有名的远程工具&#xff0c;但…

【计算机图形学】图形变换(以任意直线为对称轴的对称变换)

模块3-2 图形变换 一 实验目的 编写图形各种变换的算法 二 实验内容 1&#xff1a;任意直线的对称变换。要求将变换矩阵写在实验报告中&#xff0c;并与代码匹配。求对任意直线AxByC0的对称变换矩阵。 实验结果如下图所示&#xff1a; 1&#xff1a;预设图形初始化 2&#…

数据结构——链表(python版)

一、链表简介 链表是一种在存储单元上非连续、非顺序的存储结构。数据元素的逻辑顺序是通过链表中的指针链接次序实现。链表是由一系列的结点组成&#xff0c;结点可以在运行时动态生成。每个结点包含两部分&#xff1a;数据域与指针域。数据域存储数据元素&#xff0c;指针域…

TCP的三次握手和四次挥手

三次握手 既然我们文章要说的是TCP的三次握手&#xff0c;和四次挥手&#xff0c;那么肯定是说的连接&#xff0c;也不是说的不其他的。那么它这个连接的过程说的是什么呢&#xff1f; 我们还是从图中理解&#xff0c;这样比较好理解&#xff0c; TCP第一次握手&#xff1a;服…

gradle Task 详解

目录 Task定义和配置 Task的执行阶段 Task 的依赖 Task 指定执行顺序 Task 主gradle引入其他的gradle文件 将某一个task挂载到指定的task之后执行 gradle task官网&#xff1a;Task - Gradle DSL Task定义和配置 查看工程下所有的task&#xff0c;使用如下命令 gradle …

【Linux】浅谈eloop机制

目录 1.eloop 机制 2.eloop结构体 2.1.eloop_data结构体 2.2 Socket事件结构体 2.3 Timeout事件结构体 2.4 Signal事件结构体 3.eloop_init 4.eloop_run 4.1 signal事件 4.2 socket事件 4.3 timeout事件 1.eloop 机制 主线程中启动事件监听机制&#xff0c;对不同的…

深度学习模型压缩与优化加速

1. 简介 深度学习&#xff08;Deep Learning&#xff09;因其计算复杂度或参数冗余&#xff0c;在一些场景和设备上限制了相应的模型部署&#xff0c;需要借助模型压缩、系统优化加速、异构计算等方法突破瓶颈&#xff0c;即分别在算法模型、计算图或算子优化以及硬件加速等层…

如何优雅地停掉线程?

很久很久以前&#xff0c;在一个名为“Springboot”的村庄中&#xff0c;住着一群热爱编程的程序员。他们喜欢探索新技术、优化自己的代码&#xff0c;为了打造更好的软件而不断努力着。 在这个村庄中&#xff0c;有一个名叫小明的程序员&#xff0c;他是村庄中最优秀的程序员…

一文打通java中内存泄露

目录 前置知识 内存泄漏&#xff08;memory leak&#xff09; 内存溢出&#xff08;out of memory&#xff09; Java中内存泄露的8种情况 静态集合类 单例模式 内部类持有外部类 各种连接&#xff0c;如数据库连接、网络连接和IO连接等 变量不合理的作用域 改变哈希值 …

第二十八章 React脚手架配置代理

为了更好地理解如何在React应用程序中配置代理&#xff0c;我们需要先了解什么是代理。 代理是一种充当客户端和服务器之间中间人的服务器。当客户端向服务器发送请求时&#xff0c;代理服务器将接收请求并将其转发到服务器。服务器将响应发送回代理服务器&#xff0c;代理服务…

机器视觉工程师职场四点“心态>交流=思路>知行合一”

视觉人机器视觉团队,他们热爱机器视觉行业,爱学习,爱分享。这一路上,首先感谢粉丝们805天一如既往的支持。我想团队拥有这些粉丝,是富有的,也是我们一直创作的动力。 是否记得毕业季,自己的豪言壮语。希望你毕业三年后,无论结果如何,不忘初心,继续前行。 机器视觉工程…

Flutter 中使用 Widgetbook 管理你的组件

Flutter 中使用 Widgetbook 管理你的组件 前言 Flutter 界面开发中我们有几个痛点 &#xff1a; 与设计师协作复用一套设计规范&#xff08;figma&#xff09; 可视化的管理你的组件代码&#xff08;基础组件、业务组件&#xff09; 不同设备尺寸测试你的组件 实时修改你的测试…

python并发编程:什么是并发编程?python对并发编程有哪些支持?

Python并发编程是指同时执行多个任务的编程模式。Python提供了多种实现并发编程的方式&#xff0c;包括多线程、多进程、协程、异步IO等。 为什么要引入并发编程 假设以下两个场景&#xff1a; 场景一: 一个网络爬虫&#xff0c;按顺序爬取花了一个小时&#xff0c;采用并发…

spring-模型数据和视图---视图解析器的说明以及大量代码演示

目录 spring-模型数据 ● 说明 应用实例需求 创建后面所有代码执行成功之后跳转的vote_ok.jsp页面 方式 1: 通过 HttpServletRequest放入 request 域 创建 Master类 创建Pet类 创建model_data.jsp 修改 VoteHandler增加方法 创建vote_ok.jsp, 显示数据 完成测试(Post…