Solution -「APIO 2018」「洛谷 P4630」铁人两项
\(\mathcal{Description}\)
Link.
给定一个 \(n\) 个点 \(m\) 条边的无向图(不保证联通),求有序三元点对 \((s,c,f)\) 的个数,满足 \(s,c,f\) 互不相同,且存在一条从 \(s\) 到 \(c\) 再到 \(f\) 的简单路径。
\(n\le10^5\),\(m\le2\times10^5\)。
\(\mathcal{Solution}\)
首先考虑这样一个问题,若 \(s,c,f\) 在同一点双中,是否一定满足条件。
答案是肯定的,这里介绍一种 CF 某题解上提到的证明。
性质证明
构造网络,将点双中的每个点拆点。对于点 \(u\),连接 \((u_i,u_o,1)\)。对于原图中的边 \((u,v)\),连接 \((u_o,v_i,1)\)。对于选定的 \(s,c,f\),连接 \((S,c_i,2),(s_o,T,1),(f_o,T,1)\),接下来只需要证明该网络的最大流为 \(2\)。
那么只需要考虑最小割 \(C\)。显然 \(C\le2\),则只需证 \(C>1\)。
首先,割掉 \((S,c_i,2)\) 或同时割掉 \((s_o,T,1),(f_o,T,1)\) 都不能使 \(C\le1\)。接下来考虑其它类型的边。
割掉 \((u_i,u_o,1)\),相当于删除 \(u\) 点。因为这是一个点双,所以 \(c\) 与 \(s,f\) 仍然连通,不满足。
割掉 \((u_o,v_i,1)\),相当于删除 \((u,v)\) 边。显然其对于连通性的影响不大于删除 \(u\) 点或 \(v\) 点,由上种情况,亦不满足。
到此,有 \(C>1\)。由因为 \(C\le2\) 且 \(C\in\mathbb N\),所以 \(C=2\)。那么这样的路径一定存在,证毕。
那么如果固定 \(s,f\),合法的 \(c\) 就可以在圆方树 \(s\) 到 \(f\) 路径上的所有圆点和所有方点所代表的圆点(除去 \(s,f\))。这是因为 \(c\) 取在任意点双内部,由我们的结论,都一定可以从某点进入点双,经过 \(c\),再从某点走出点双。
但简单的计算会导致重复——一个圆点对多个方点有贡献。
举个例子,对于 \(u-w-v\),\(w\) 是圆点,\(u,v\) 是方点,如果我们单纯地用点双大小作为方点的权值,\(w\) 就会在 \(u\) 和 \(v\) 中分别计算一次。
解决办法很巧妙:将圆点的权值设为 \(-1\)。考虑 \(s\) 到 \(f\) 的路径必然是”圆-方-圆-……-圆-方-圆“,两个端点的 \(-1\),去除了 \(s\) 和 \(f\) 的贡献,中间的 \(-1\) 去除了在左右的”方“中重复的贡献。那么,合法的 \(c\) 的数量就是 \(s\) 到 \(f\) 的树上路径权值之和。
于是,相当于求树上点对的路径权值和。反过来,固定 \(c\),维护子树信息求出 \((s,f)\) 的方案数,计算 \(c\) 的贡献即可。
复杂度 \(\mathcal O(n)\)。
\(\mathcal{Code}\)
#include <cstdio>
const int MAXN = 1e5, MAXM = 2e5;
int n, m, q, snode;
int dfc, top, dfn[MAXN + 5], low[MAXN + 5], stk[MAXN + 5];
int siz[MAXN * 2 + 5], val[MAXN * 2 + 5];
long long ans;
struct Graph {
int ecnt, head[MAXN * 2 + 5], to[MAXM * 2 + 5], nxt[MAXM * 2 + 5];
inline void link ( const int s, const int t ) {
to[++ ecnt] = t, nxt[ecnt] = head[s];
head[s] = ecnt;
}
inline void add ( const int u, const int v ) {
link ( u, v ), link ( v, u );
}
} src, tre;
inline bool chkmin ( int& a, const int b ) { return b < a ? a = b, true : false; }
inline void Tarjan ( const int u, const int f ) {
dfn[u] = low[u] = ++ dfc, val[stk[++ top] = u] = -1;
for ( int i = src.head[u], v; i; i = src.nxt[i] ) {
if ( ( v = src.to[i] ) == f ) continue;
if ( ! dfn[v] ) {
Tarjan ( v, u ), chkmin ( low[u], low[v] );
if ( low[v] >= dfn[u] ) {
tre.add ( u, ++ snode ), val[snode] = 1;
do tre.add ( snode, stk[top] ), ++ val[snode]; while ( stk[top --] ^ v );
}
} else chkmin ( low[u], dfn[v] );
}
}
inline void calc ( const int u, const int f ) {
siz[u] = u <= n;
for ( int i = tre.head[u], v; i; i = tre.nxt[i] ) {
if ( ( v = tre.to[i] ) ^ f ) {
calc ( v, u );
ans += 1ll * val[u] * siz[u] * siz[v];
siz[u] += siz[v];
}
}
ans += 1ll * val[u] * siz[u] * ( dfc - siz[u] );
}
int main () {
scanf ( "%d %d", &n, &m ), snode = n;
for ( int i = 1, u, v; i <= m; ++ i ) {
scanf ( "%d %d", &u, &v );
src.add ( u, v );
}
for ( int i = 1; i <= n; ++ i ) {
if ( ! dfn[i] ) {
dfc = top = 0;
Tarjan ( i, 0 );
calc ( i, 0 );
}
}
printf ( "%lld\n", ans << 1 );
return 0;
}
Solution -「APIO 2018」「洛谷 P4630」铁人两项的更多相关文章
- 洛谷P4630 [APIO2018]铁人两项 [广义圆方树]
传送门 又学会了一个新东西好开心呢~ 思路 显然,假如枚举了起始点\(x\)和终止点\(y\),中转点就必须在它们之间的简单路径上. 不知为何想到了圆方树,可以发现,如果把方点的权值记为双联通分量的大 ...
- 「区间DP」「洛谷P1043」数字游戏
「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...
- 洛谷P4630 [APIO2018] Duathlon 铁人两项 【圆方树】
题目链接 洛谷P4630 题解 看了一下部分分,觉得树的部分很可做,就相当于求一个点对路径长之和的东西,考虑一下能不能转化到一般图来? 一般图要转为树,就使用圆方树呗 思考一下发现,两点之间经过的点双 ...
- Solution -「APIO 2016」「洛谷 P3643」划艇
\(\mathcal{Description}\) Link & 双倍经验. 给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...
- Solution -「JSOI 2019」「洛谷 P5334」节日庆典
\(\mathscr{Description}\) Link. 给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的). \(|S|\le3\time ...
- Solution -「洛谷 P4372」Out of Sorts P
\(\mathcal{Description}\) OurOJ & 洛谷 P4372(几乎一致) 设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...
- Solution -「POI 2010」「洛谷 P3511」MOS-Bridges
\(\mathcal{Description}\) Link.(洛谷上这翻译真的一言难尽呐. 给定一个 \(n\) 个点 \(m\) 条边的无向图,一条边 \((u,v,a,b)\) 表示从 ...
- Solution -「JSOI2008」「洛谷 P4208」最小生成树计数
\(\mathcal{Description}\) link. 给定带权简单无向图,求其最小生成树个数. 顶点数 \(n\le10^2\),边数 \(m\le10^3\),相同边权的边数不 ...
- Solution -「洛谷 P6158」封锁
\(\mathcal{Description}\) Link. 给定一个 \(n\times n\) 的格点图,横纵相邻的两格点有一条边权为二元组 \((w,e)\) 的边.求对于 \(S=( ...
随机推荐
- Windows 10 安装 Git 与初次运行前的配置
Windows 10 安装 Git 与初次运行前的配置 在 Windows 上安装 初次运行 Git 前的配置 用户信息 文本编辑器 检查配置信息 获取 Git 仓库 在现有目录中初始化仓库 克隆现有 ...
- 一键AI着色,黑白老照片画面瞬间鲜活
很多老照片或者电影受时代技术所限制,只能以黑白形式保存:经过编辑后的黑白视频和图片早已丢失彩色原图,这对于保存者来说都十分遗憾.如何能将单一乏味.陈旧斑驳的黑白照片变成鲜活亮丽的彩色照片,从照片中重新 ...
- 面试官问,Redis 是单线程还是多线程?我懵了
我们平时看到介绍 Redis 的文章,都会说 Redis 是单线程的.但是我们学习的时候,比如 Redis 的 bgsave 命令,它的作用是在后台异步保存当前数据库的数据到磁盘,那既然是异步了,肯定 ...
- python分支结构与循环结构
python分支结构 一.if 单条件形式 # 年轻人的世界都不容易 age > 18 age = int(input("请输入您的年龄:")) # input()函数 模拟 ...
- 一条 Git 命令减少了一般存储空间,我的服务器在偷着笑
元旦不是搭建了一个<Java 程序员进阶之路>的网站嘛,其中用到了 Git 来作为云服务器和 GitHub 远程仓库之间的同步工具. 作为开发者,相信大家都知道 Git 的重要性.Git ...
- 【刷题-LeetCode】209. Minimum Size Subarray Sum
Minimum Size Subarray Sum Given an array of n positive integers and a positive integer s, find the m ...
- 今天太开心了,因为我知道了seastar框架
今天听说了一个新的C++语言开发的网络框架,叫做seastar. seastar有何特别之处呢?先看看官网提供的性能数据: 性能 HTTPD benchmark: cpu # request/sec ...
- Spring Boot 3.0.0 发布第一个里程碑版本M1,你的 Java 升到17 了吗?
2022年1月20日,Spring官方发布了Spring Boot 3.0.0的第一个里程碑版本M1. 下面一起来来看看Spring Boot 3.0.0 M1版本都有哪些重大变化: Java基线从 ...
- gin框架中多种数据格式返回请求结果
返回四种格式的数据:1. []byte.string 2. json格式 3. html模板渲染 4. 静态资源设置 package main import ( "github.com ...
- IoC容器-Bean管理(bean生命周期)
1,生命周期 即从对象创建到对象销毁的过程 2,bean生命周期 (1)通过构造器创建bean实例(无参数构造) (2)为bean的属性设置值和对其他bean的引用(调用set方法) (3)调用bea ...