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

AT_jsc2019_qual_e Card Collector题解

博客地址

图论建模还是太神仙了。

首先思考一下题目给的条件,每行只选一个,接着每列只选一个,由于这种唯一对应的性质,很容易让人想到二分图匹配,但数据范围并不允许我们这样做。

但这给我们一个图论建模的思路。考虑一张卡片在 \((x,y)\) 上,权值为 \(v\),我们可以看作在点 \(x\) 和点 \(y+r\) 之间连了一条权值为 \(v\) 的边。为了区分第一步操作和第二步操作,有一个 trick 是让边有方向。钦定如果是在第一步操作中(即从每一行中选取卡片),让边的方向为 \(x\)\(y+r\),否则让边的方向为 \(y+r\)\(x\)

接下来研究一下图的性质。根据题目限制我们可以发现一个点最多只能向外连一条边(因为若不保证这一点,则根据钦定的变的定义,会出现一行选取多个点或一列选取多个点的情况),即出度为 \(1\),这显然就是内向基环树森林。

但有向边不好处理,所以接下来一步比较奇妙的处理就是让有向边变成无向边。那么为什么可以直接转换?我们只要保证一个点在有向图中出度为 \(1\) 即可保证方案合法,那么再边变为无向后的新图中只要保证每一个联通块都是树或基环树。

稍微证明一下:如果是树,一种构造方法是让边的方向一致朝下。如果是基环树,只要让环部分的边转一圈回到起始点,其他边向环的方向指即可。如下图所示:

那么唯一的问题在于如何求出选哪些边是的它们组成一颗颗树或者基环树。其实只用在 Kruskal 求最大生成树的过程中加一个标记数组标记该连通块是基环数还是树即可。遵循以下规则:

  • 如果联通块内部点相连接,那么该联通块一定是一棵树,连完后它成为一颗基环树。

  • 如果是两个联通块相连,那么一定不能是两个基环树,假如两个联通块有一个是基环树,那么连完后整体是基环树,反之是树。

可自行证明一下这样做一定是符合定义的,并不难证。

代码如下:

#include <bits/stdc++.h>
#define int long long
using namespace std;
struct A {int x, y, v;bool operator<(const A &h) const { return v < h.v; }
} e[5000000];
int tmp;
int t[5000000];
bool cmp(A x, A y) { return x.v > y.v; }
int find(int x) {if (t[x] == x) {return x;}return t[x] = find(t[x]);
}
int bz[5000000];
signed main() {int n, r, c;scanf("%lld%lld%lld", &n, &r, &c);for (int i = 1; i <= n; i++) {int x, y, v;scanf("%lld%lld%lld", &x, &y, &v);e[++tmp] = { x, y + r, v };}sort(e + 1, e + 1 + tmp, cmp);for (int i = 1; i <= r + c; i++) {t[i] = i;}int ans = 0;for (int i = 1; i <= tmp; i++) {int fx = find(e[i].x), fy = find(e[i].y);if (fx == fy) {if (!bz[fx]) {ans += e[i].v;bz[fx] = 1;}continue;}if (!bz[fx] || !bz[fy]) {t[fx] = fy;bz[fy] =bz[fx]=bz[fy]|bz[fx];ans += e[i].v;}}printf("%lld", ans);
}
http://www.zskr.cn/news/51464.html

相关文章:

  • 20251115ACC
  • 完整教程:(Linux) WSL 通过 VSCode 连接不执行 profile 问题(登录Shell问题)
  • python多进程通信 —— 两进程通信 —— Pipe与Queue的通信性能对比
  • noip7
  • dns服务详解
  • 一乐人物志
  • 详细介绍:基于Spring Boot的高校实习实践管理系统(源码+论文+部署+安装)
  • xml.etree.ElementTree 完全支持嵌套查找子元素,且有多种简洁实用的方式。
  • 开源软件的崛起:技术共享与协作创新的新时代 - 详解
  • AT_agc063_e Child to Parent 题解
  • 这里是 NoInt_Young 的博客
  • CF 2156E Best Time to Buy and Sell Stock
  • 《重生之我成为世界顶级黑客》第七章:成功了,但没完全成功
  • 实用指南:Open Inventor 2025.2 FOR JAVA
  • 2025年中小学生 AI 学习机选购指南:松鼠 AI 双线模式成优选
  • 20232305 2025-2026-1 《网络与系统攻防技术》实验五实验报告
  • 网络分析模型六
  • Docker - 配置镜像站解决下载镜像的网络问题
  • Linux问题
  • 20232424 2025-2026-1 《网络与系统攻防技术》实验五实验报告
  • 【C++STL :stack queue (二) 】stack 与 queue 的模拟实现与双端队列探秘 - 指南
  • 《重生之我成为世界顶级黑客》第五章:失败,失败,还是失败
  • 利用单片机的TIM模块播放春日影
  • warp-cli代理
  • 20231427田泽航tlcp协议验证
  • 20232412 2024-2025-1 《网络与系统攻防技术》实验五实验报告
  • 本地缓存Caffeien
  • 实用指南:C++---嵌套类型(Nested Types)封装与泛型的基石
  • python: 用pyppeteer以无头方式抓取页面
  • python共享内存的读写同步与加锁 —— multiprocessing.Value和multiprocessing.Array、加锁