当前位置: 首页 > news >正文

Codeforces Round 1021 (Div. 2) D. Baggage Claim(建图)

每周五篇博客:(4/5)

https://codeforces.com/contest/2098/problem/D

题意

每个机场都有一个行李索赔区,巴尔贝索沃机场也不例外。在某个时候,Sheremetyevo的一位管理员提出了一个不寻常的想法:将行李索赔传送带的传统形状从轮播更改为更复杂的形式。

假设行李索赔区域表示为大小 n × m n \times m n×m 的矩形网格。管理局提出,输送机的路径应通过 p 1 , p 2 , … , p 2 k + 1 p_1, p_2, \ldots, p_{2k+1} p1,p2,,p2k+1 的单元,其中 p i = ( x i , y i ) p_i = (x_i, y_i) pi=(xi,yi)

对于每个单元格 p i p_i pi 和下一个单元格 p i + 1 p_{i+1} pi+1 (其中 1 ≤ i ≤ 2 k 1 \leq i \leq 2k 1i2k ),这些单元格必须具有共同的侧面。此外,路径必须很简单,这意味着对于没有一对索引 i ≠ j i \neq j i=j ,如果单元格 p i p_i pi p j p_j pj 的单元格。

不幸的是,路线计划被溢出的咖啡意外宠坏了,只保留了带有奇数指数的细胞: p 1 , p 3 , p 5 , … , p 2 k + 1 p_1, p_3, p_5, \ldots, p_{2k+1} p1,p3,p5,,p2k+1 。您的任务是确定给定这些 k + 1 k+1 k+1 单元格的原始完整路径 p 1 , p 2 , … , p 2 k + 1 p_1, p_2, \ldots, p_{2k+1} p1,p2,,p2k+1 的方法数量。

由于答案可能很大,因此输出它模拟 1 0 9 + 7 10^9+7 109+7

思路

首先对于 p 2 i − 1 , p 2 i + 1 p_{2i - 1},p_{2i + 1} p2i1,p2i+1 ,如果 ∣ p 2 i − 1 − p 2 i + 1 ∣ ≠ 2 |p_{2i - 1}-p_{2i + 1}| \ne 2 p2i1p2i+1=2 的话答案一定是 0 0 0 ,即我们无法通过两步的操作从 p 2 i − 1 p_{2i - 1} p2i1 走到 p 2 i + 1 p_{2i + 1} p2i+1

接下来我们进行建图,如果 p 2 i − 1 p_{2i - 1} p2i1 p 2 i + 1 p_{2i + 1} p2i+1 处于同一行/同一列,那么在他们中间的点连一条自环边;如果 p 2 i − 1 p_{2i - 1} p2i1 p 2 i + 1 p_{2i + 1} p2i+1 不处于同一行/同一列,那么我们在这两个点之间可以通过的两个点进行连边

例如点 ( 1 , 1 ) , ( 1 , 3 ) (1, 1), (1, 3) (1,1),(1,3) ,那么我们会在点 ( 1 , 2 ) (1, 2) (1,2) 处连一条 ( 1 , 2 ) − ( 1 , 2 ) (1, 2) - (1, 2) (1,2)(1,2) 的无向边

例如点 ( 1 , 1 ) , ( 2 , 2 ) (1, 1), (2, 2) (1,1),(2,2) ,那么我们会在点 ( 1 , 2 ) (1, 2) (1,2) ( 2 , 1 ) (2, 1) (2,1) 处连一条 ( 1 , 2 ) − ( 2 , 1 ) (1, 2) - (2,1) (1,2)(2,1) 的无向边

连边本质上是我们让可以作为 p 2 i p_{2i} p2i 的点之间连接起来,意思是只要我们选择边的某个端点都是合法的一种方案作为链接 p 2 i − 1 , p 2 i + 1 p_{2i - 1},p_{2i + 1} p2i1,p2i+1

连边后我们会获得若干个连通块,而这些连通块有以下几种可能:

  1. 如果该连通块的点数比边数要少,那么答案为 0 0 0 。这是因为我们每链接一条边都代表我们需要去选择一个点去链接某对 p 2 i − 1 , p 2 i + 1 p_{2i - 1},p_{2i + 1} p2i1,p2i+1 。如果边比点多的话,那么点数根本就不够选择的,所以答案一定是 0 0 0
  2. 如果该连通块的点数和边数一样,表示该连通块一定存在环,那么同样分成两种情况
    1. 该环是某个节点的自环。此时答案根据乘法原理乘以 1 1 1 。原因见另一种情况的解释
    2. 该环包含了超过一个节点的环。此时答案根据乘法原理乘以 2 2 2 。这个情况可以参考题目的样例 2 2 2 。如果我们选择一个点来固定的话,那么其余点的选择也都固定了。而对于 p 2 i − 1 , p 2 i + 1 p_{2i - 1},p_{2i + 1} p2i1,p2i+1 中的 p 2 i p_{2i} p2i 有两种选择的可能,所以选择的点都有两种方案,那么答案也就是两种了。同理,对于上一种情况,因为有一个 p 2 i p_{2i} p2i 点是唯一选择的,那么答案只能乘以 1 1 1
  3. 如果该连通块的点数比边数要多,那么该连通块一定是棵树,并且答案根据乘法原理乘以点的数量即可。这是因为我们要选边的数量的点来作为一种可行的方案,所以在这棵树中我们可以选择任意一个点作为无用点后可以得到一个固定的可行方案,而这个无用点的选择方案有点的数量个

事实上我们也不需要实际建边再去跑连通分量,只需要用并查集维护每个点都在哪些连通块即可,具体细节见代码

代码

struct DSU {int n;std::vector<int> fa, sz;std::vector<i64> val;explicit DSU(int n): n(n) {fa.assign(n + 1, 0);sz.assign(n + 1, 1);val.assign(n + 1, 0);for (int i = 1; i <= n; i ++) fa[i] = i;}int find(int x) {if (x == fa[x]) return fa[x];int f = fa[x];fa[x] = find(fa[x]);val[x] += val[f];return fa[x];}bool judge(int x, int y) {int dx = find(x), dy = find(y);if (dx == dy) return true;else return false;}void merge(int x, int y, i64 w = 0) {int dx = find(x), dy = find(y);if (dx != dy) {fa[dx] = dy;sz[dy] += sz[dx];val[dx] = -val[x] + val[y] + w;}}
};void solve() {int n, m, k;std::cin >> n >> m >> k;DSU dsu(n * m);std::vector<int> cnt(n * m + 1), loop(n * m + 1);auto get = [&](int x, int y) {return (x - 1) * m + y;};std::vector<PII> a(k + 1);for (int i = 0; i <= k; i ++) std::cin >> a[i].first >> a[i].second;for (int i = 1; i <= k; i ++) {auto [x1, y1] = a[i - 1];auto [x2, y2] = a[i];if (std::abs(x1 - x2) + std::abs(y1 - y2) != 2) {std::cout << "0\n";return ;}int u, v;if (std::abs(x1 - x2) == 1) {u = get(x1, y2), v = get(x2, y1);} else if (x1 == x2) {u = get(x1, (y1 + y2) / 2), v = get(x1, (y1 + y2) / 2);} else if (y1 == y2) {u = get((x1 + x2) / 2, y1), v = get((x1 + x2) / 2, y1);}if (!dsu.judge(u, v)) {cnt[dsu.find(u)] += cnt[dsu.find(v)];loop[dsu.find(u)] |= loop[dsu.find(v)];dsu.merge(v, u);}cnt[dsu.find(u)] ++;if (u == v) loop[dsu.find(u)] = 1;}Z ans = 1;for (int i = 0; i <= n * m; i ++) if (dsu.find(i) == i) {int sz = dsu.sz[i];if (sz < cnt[i]) {ans = 0;break;} else if (sz == cnt[i]) {if (loop[i]) {ans *= 1;} else {ans *= 2;}} else {ans *= sz;}}std::cout << ans << '\n';
}

相关文章:

  • PLC在仪表控制系统中的应用
  • 代码随想录算法训练营第60期第二十天打卡
  • Python爬虫(6)静态页面解析实战:BeautifulSoup与lxml(XPath)高效提取数据指南
  • 能源行业数字化转型:利用大数据与人工智能提升效率与可持续性
  • MCP Server On FC 之旅1: MCP 协议的深度解析与云上适配最佳实践
  • Docker 部署 flink1.19.2
  • Golang 学习指南
  • 基于ArcGIS的洪水淹没分析技术-洪水灾害普查、风险评估及淹没制图中的实践技术
  • Rollup、Webpack、Esbuild 和 Vite 前端打包工具
  • django.db.models.query_utils.DeferredAttribute object
  • Go RPC 服务方法签名的要求
  • Spark-Streaming3
  • Nacos简介—4.Nacos架构和原理一
  • 树莓派超全系列教程文档--(44)如何在树莓派上编译树莓派内核
  • 如何实现一个可视化的文字编辑器(C语言版)?
  • 优考试V4.20机构版【附百度网盘链接】
  • RabbitMQ应用(基于腾讯云)
  • 基于定制开发开源AI智能名片S2B2C商城小程序的会员存量池构建策略研究
  • 区块链基石解码:分布式账本的运行奥秘与技术架构
  • 助力产业升级 | BMC安全启动方案上新了!
  • 我国对国家发展规划专门立法
  • 大学2025丨专访北邮校长徐坤:工科教育要真正回归工程本质
  • 文庙印象:一周城市生活
  • 记录发生真相,南沙岛礁生态调查纪实片《归巢》发布
  • 北京市平谷区政协原主席王春辉接受纪律审查和监察调查
  • 山东一季度GDP为23466亿元,同比增长6.0%