Codeforces Round 884 E. Great Grids

E. Great Grids

E

题意

一个 n × m n \times m n×m 的网格图是 g o o d good good 的当且仅当:

  • 每个网格的字符是 A 、 B 、 C A、B、C ABC 中的一种
  • 每一个 2 × 2 2 \times 2 2×2 的子格都包含三种不同的字符
  • 相邻的格子字符不一样

现在给定 k k k 个限制条件,每个限制条件约定:
( x 1 , y 1 ) (x_1,y_1) (x1,y1) ( x 2 , y 2 ) (x_2,y_2) (x2,y2) 的字符一样,并且这两个格子是对角格

问满足所有约束条件的 g o o d good good 网格图是否存在

题意

观察发现:每一个 2 × 2 2 \times 2 2×2 的子格,它的其中一对对角格一定相同,另外一对对角格一定不同。我们先把三种字符转化成数字: 0 、 1 、 2 0、1、2 012,然后我们在每个格子画一个向右向下的箭头,权值为相邻数字的权值差 3 3 3

例如:
a → b a \rarr b ab
↓ ↓ \darr \hspace{15pt} \darr
b → c b \rarr c bc

转化成:
0 → 2 1 0 \stackrel{2} \rarr 1 021
↓ 2 ↓ 2 \darr \stackrel{2} {} \hspace{15pt} \darr \stackrel{2} {} 22
1 → 2 2 1 \stackrel{2} \rarr 2 122

上面这个摆放方式很特殊,因为这是其中一种情况:右上左下是相等字符,如果是另外一个对角格是相等的,横线和竖线就不相等。但是不管是哪个对角格相等,同一列的横线之间的边权一定是相等的,同理,同一行的竖线的边权也是相等的。

证明:假设相同的数字是 x x x,另外两个数字是 x 1 x_1 x1 x 2 x_2 x2,并且假设相等的对角格是右上和左下(另外一种情况也是对称),那么:
( x 1 − x ) ≡ ( x − x 2 ) ( m o d 3 ) \quad (x_1 - x) \equiv (x - x_2) \quad (mod 3) (x1x)(xx2)(mod3)
⇔ x 1 + x 2 ≡ 2 x ( m o d 3 ) \Leftrightarrow x_1 + x_2 \equiv 2x \quad (mod 3) x1+x22x(mod3)
⇔ x 1 + x 2 ≡ 2 ( 3 − ( x 1 + x 2 ) ) ( m o d 3 ) \Leftrightarrow x_1 + x_2 \equiv 2(3 - (x_1 + x_2)) \quad (mod 3) x1+x22(3(x1+x2))(mod3)
⇔ x 1 + x 2 ≡ 6 − 2 ( x 1 + x 2 ) ( m o d 3 ) \Leftrightarrow x_1 + x_2 \equiv 6 - 2(x_1 + x_2) \quad (mod 3) x1+x262(x1+x2)(mod3)
⇔ 3 ( x 1 + x 2 ) ≡ 6 ( m o d 3 ) \Leftrightarrow 3(x_1 + x_2) \equiv 6 \quad (mod 3) 3(x1+x2)6(mod3)
可以发现:同余式两边都是 0 0 0,显然同余

其他情况也可以类比出来。
那么现在我们一共有 n − 1 n-1 n1 条竖线, m − 1 m-1 m1 条横线,也就是一共 n + m − 2 n + m - 2 n+m2 个变量。
如果相等的对角格是右上左下这种情况,那么对应的横线和竖线边权相等
另外一种情况就是不等。

因此对于 k k k 个限制条件,我们建立相应的边,跑 2 S A T 2_SAT 2SAT二分图染色 就可以得出答案

#include<bits/stdc++.h>
#define fore(i,l,r)	for(int i=(int)(l);i<(int)(r);++i)
#define fi first
#define se second
#define endl '\n'
#define ull unsigned long long
#define ALL(v) v.begin(), v.end()
#define Debug(x, ed) std::cerr << #x << " = " << x << ed;

const int INF=0x3f3f3f3f;
const long long INFLL=1e18;

typedef long long ll;

std::vector<int> sccno;
std::vector<std::vector<int>> g;
int D;
std::vector<int> low;
std::vector<int> dfn;
int tot;
std::stack<int> st;
int n, m, k;

void Tarjan(int u){
    st.push(u);
    dfn[u] = low[u] = ++tot;
    for(auto v : g[u])
        if(!dfn[v]){
            Tarjan(v);
            low[u] = std::min(low[u], low[v]);
        }
        else if(!sccno[v]) low[u] = std::min(low[u], dfn[v]);
    if(low[u] == dfn[u]){
        ++tot;
        while(true){
            int v = st.top();
            st.pop();
            sccno[v] = tot;
            if(v == u) break;
        }
    }
}

bool two_sat(){
    fore(i, 1, 2 * (n + m - 2) + 1)
        if(!dfn[i])
            Tarjan(i);
    fore(i, 1, n + m - 1)
        if(sccno[i] == sccno[i + D])
            return false;
    return true;
}

int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    int t;
    std::cin >> t;
    while(t--){
        std::cin >> n >> m >> k;
        sccno.assign(2 * (n + m + 5), 0);
        g.assign(2 * (n + m + 5), std::vector<int>());
        low.assign(2 * (n + m + 5), 0);
        dfn.assign(2 * (n + m + 5), 0);
        tot = 0;
        D = n + m - 2;
        while(k--){
            int x1, y1, x2, y2;
            std::cin >> x1 >> y1 >> x2 >> y2;
            if(y1 + 1 == y2){
                int u = x1, v = n - 1 + y1;
                g[u].push_back(v + D);
                g[v].push_back(u + D);
                g[u + D].push_back(v);
                g[v + D].push_back(u);
            }
            else{
                int u = x1, v = n - 1 + y2;
                g[u].push_back(v);
                g[v].push_back(u);
                g[u + D].push_back(v + D);
                g[v + D].push_back(u + D);
            }
        }
        std::cout << (two_sat() ? "YES" : "NO") << endl;
    }
    return 0;
}

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

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

相关文章

【Redis】实现缓存及相关问题

Redis实现缓存及相关问题 认识缓存 缓存就是数据交换的缓冲区&#xff0c;是存贮数据的临时地方&#xff0c;一般读写性能较高。 缓存的作用&#xff1a; 降低后端负载提高读写效率&#xff0c;降低响应时间 缓存的成本&#xff1a; 数据一致性成本代码维护成本运维成本 …

PXE高效批量装机

一、系统安装 1. 系统装机的三种引导方式 1. 硬盘安装 2. 光驱&#xff08;u盘&#xff09;安装 3. 网络启动 pxe 2.系统安装过程 加载boot loader Boot Loader 是在操作系统内核运行之前运行的一段小程序。通过这段小程序&#xff0c;我们可以初始化硬件设备、建立内…

C#使用OpenCvSharp4库中5个基础函数-灰度化、高斯模糊、Canny边缘检测、膨胀、腐蚀

C#使用OpenCvSharp4库中5个基础函数-灰度化、高斯模糊、Canny边缘检测、膨胀、腐蚀 使用OpenCV可以对彩色原始图像进行基本的处理&#xff0c;涉及到5个常用的处理&#xff1a; 灰度化 模糊处理 Canny边缘检测 膨胀 腐蚀 1、测试图像lena.jpg 本例中我们采用数字图像处…

day39_mysql

今日内容 0 复习昨日 1 DML 2 约束 3 DQL 0 复习昨日 1 什么是数据库(Database)? 用来组织,存储,管理数据的仓库 2 什么是数据库管理系统(Database Management System-DBMS)? 用来管理数据库的一个软件 3 数据库分类 关系型数据库,Oracle,Mysql,SqlServer,DB2非关系数据库,Re…

深入理解Java中的ForkJoin框架原理

在现代多核处理器的时代&#xff0c;有效地利用并行计算可以极大地提高程序的性能。Java中的ForkJoin框架是Java 7引入的一个并行计算框架&#xff0c;它提供了一种简单而高效的方式来利用多核处理器。在本文中&#xff0c;我们将深入探讨ForkJoin框架的原理和工作方式。 一、什…

《区块链简易速速上手小册》第10章:区块链的未来与趋势(2024 最新版)

文章目录 10.1 区块链的未来展望10.1.1 基础知识10.1.2 主要案例&#xff1a;区块链在金融领域的发展10.1.3 拓展案例 1&#xff1a;区块链在供应链管理中的应用10.1.4 拓展案例 2&#xff1a;区块链在身份管理和隐私保护中的应用 10.2 新兴技术与区块链的融合10.2.1 基础知识1…

数据结构之图

图 图&#xff08;Graph&#xff09;是比树还要难以理解和学习的“多对多”数据结构&#xff0c;可以认为树也是图的一种。图的知识点众多&#xff0c;按照存储路径的方向分&#xff0c;可分为无向图和有向图&#xff0c;按照图的存储结构分&#xff0c;可分为完全图与有向完全…

InstantID: Zero-shot Identity-Preserving Generation in Seconds

文章目录 IntroductionMainReference 记录由国内首创的一个好玩的小项目&#xff0c;图像生成领域的新进展。但我希望现阶段计算机视觉领域的研究能更聚焦在 语义分割 和 三维视觉 上&#xff0c;这样能更方便与机器人等产品和工业实体结合。 Introduction InstantID 是一个基…

phpstudy安装并运行redis

对于一个菜鸟来说&#xff0c;任何一个小步骤都可能研究半天&#xff0c;比如“phpstudy安装并运行redis”这一问题&#xff0c;解决好后第一时间记录下来&#xff0c;方便日后查看&#xff0c;也为遇到同样困难的小伙伴提供个参考&#xff01; 一、phpstudy安装redis 1.打开…

部署monggodb副本集分片集群

分片技术,可以满足MongoDB数据量大量增长的需求。当MongoDB存储海量的数据时&#xff0c;一台机器可能不足以存储数据&#xff0c;也可能不足以提供可接受的读写吞吐量。这时&#xff0c;我们就可以通过在多台机器上分割数据&#xff0c;使得数据库系统能存储和处理更多的数据。…

不废话的将ts一篇文章写完

写在前面 网上很多写ts的教程的&#xff0c;但是我觉得写的太繁琐了&#xff0c;这里我直接将基础用法写上&#xff0c;包括编译后的js代码&#xff0c;以便于你们进行对比&#xff0c; 包括一些常见的报错信息&#xff0c;你们可以对比一下报错信息&#xff0c; 我尽量不废话的…

图形化编程:Scratch与6547网题库的奇妙结合

随着科技的飞速发展&#xff0c;编程教育逐渐成为孩子们不可或缺的技能。其中&#xff0c;图形化编程因其简单易懂的特性&#xff0c;受到了广大儿童的喜爱。Scratch&#xff0c;这一由麻省理工学院开发的编程工具&#xff0c;正是引领这一风潮的佼佼者。与此同时&#xff0c;6…

LeetCode202. 快乐数

202. 快乐数 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。如果这个过程 结果为…

HTML5的新特性

目录 一&#xff0c;新增语义化标签 二&#xff0c;新增的多媒体标签 三&#xff0c;新增input表单 四&#xff0c;新增的表单属性 一&#xff0c;新增语义化标签 二&#xff0c;新增的多媒体标签 1&#xff0c;音频&#xff1a;<audio>.。。用MP3 <audio src…

JavaScript 基础五 对象

JavaScript 基础五 对象 1. 对象2. 对象使用① 声明语法② 对象有属性和方法组成③ 属性对象属性的增删改查操作 ④ 方法 3. 对象遍历实例 4. 内置对象① 内置对象② 内置对象Math属性方法 引入&#xff1a;保存网站用户信息&#xff0c;比如姓名、年龄、电话号码&#xff0c;用…

ENG-2,可用于监测细胞内钠离子的动态变化

Replacement of Asante NaTrium Green-2 AM钠离子指示探针&#xff0c;ENG-2&#xff0c;可用于监测细胞内钠离子的动态变化 您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;Replacement of Asante NaTrium Green-2 AM钠离子指示探针&#xff0c;ENG-2 一、基本信…

如何对视频进行翻译

下载视频和翻译软件 视频和翻译软件点击下载就行了&#xff0c;下载之后解压&#xff0c;然后把两个exe点一下。接下来如果资金充裕或者要求比较高的可以使用各个api&#xff0c;网站里有视频介绍了。 经济适用视频翻译 原理简析 首先这个软件对视频的翻译的流程大致如下&a…

使用Python的Turtle模块简单绘制烟花效果

import turtle import random# 初始化屏幕 screen turtle.Screen() screen.bgcolor("black") screen.title("烟花模拟")# 创建一个Turtle来绘制烟花 firework turtle.Turtle() firework.hideturtle() firework.speed(0) # 设置绘图速度为最快# 绘制烟花…

如何系统的自学Python?通义千问、讯飞星火、文心一言及ChatGPT的回答

如何系统的自学Python&#xff1f;来看看通义千问、讯飞星火、文心一言及ChatGPT的回答. 第一个是马老师的通义千问 系统地自学Python是一个循序渐进的过程&#xff0c;从基础语法到实践项目&#xff0c;再到专业领域的深入学习。下面是一个详细的步骤指南&#xff1a; 了解Py…

vulhub靶机activemq环境下的CVE-2015-5254(ActiveMQ 反序列化漏洞)

影响范围 Apache ActiveMQ 5.x ~ Apache ActiveMQ 5.13.0 远程攻击者可以制作一个特殊的序列化 Java 消息服务 (JMS) ObjectMessage 对象&#xff0c;利用该漏洞执行任意代码。 漏洞搭建 没有特殊要求&#xff0c;请看 (3条消息) vulhub搭建方法_himobrinehacken的博客-CSD…