\(\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」铁人两项的更多相关文章

  1. 洛谷P4630 [APIO2018]铁人两项 [广义圆方树]

    传送门 又学会了一个新东西好开心呢~ 思路 显然,假如枚举了起始点\(x\)和终止点\(y\),中转点就必须在它们之间的简单路径上. 不知为何想到了圆方树,可以发现,如果把方点的权值记为双联通分量的大 ...

  2. 「区间DP」「洛谷P1043」数字游戏

    「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...

  3. 洛谷P4630 [APIO2018] Duathlon 铁人两项 【圆方树】

    题目链接 洛谷P4630 题解 看了一下部分分,觉得树的部分很可做,就相当于求一个点对路径长之和的东西,考虑一下能不能转化到一般图来? 一般图要转为树,就使用圆方树呗 思考一下发现,两点之间经过的点双 ...

  4. Solution -「APIO 2016」「洛谷 P3643」划艇

    \(\mathcal{Description}\)   Link & 双倍经验.   给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...

  5. Solution -「JSOI 2019」「洛谷 P5334」节日庆典

    \(\mathscr{Description}\)   Link.   给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的).   \(|S|\le3\time ...

  6. Solution -「洛谷 P4372」Out of Sorts P

    \(\mathcal{Description}\)   OurOJ & 洛谷 P4372(几乎一致)   设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...

  7. Solution -「POI 2010」「洛谷 P3511」MOS-Bridges

    \(\mathcal{Description}\)   Link.(洛谷上这翻译真的一言难尽呐.   给定一个 \(n\) 个点 \(m\) 条边的无向图,一条边 \((u,v,a,b)\) 表示从 ...

  8. Solution -「JSOI2008」「洛谷 P4208」最小生成树计数

    \(\mathcal{Description}\)   link.   给定带权简单无向图,求其最小生成树个数.   顶点数 \(n\le10^2\),边数 \(m\le10^3\),相同边权的边数不 ...

  9. Solution -「洛谷 P6158」封锁

    \(\mathcal{Description}\)   Link.   给定一个 \(n\times n\) 的格点图,横纵相邻的两格点有一条边权为二元组 \((w,e)\) 的边.求对于 \(S=( ...

随机推荐

  1. 原生android webview 显示的H5页面颜色属性无法识别 - 具体解决心得

    1.前言 background-color: #fc1717bf; 这个样式属性没毛病吧,浏览器都是支持的,但是在android 7.0 系统无法正确识别这个含有透明度的属性, 即bf无法识别,将默认 ...

  2. spring cloud --- 使用 actuator 热更新【刷新】单机配置文件

    1.前言 分布式微服务想要热更新配置文件,还需要 消息中间件 配合使用 ,一般使用 rabbitMQ 或 Kafka ,这里不解释 . 这篇随笔 只讲解 底层的 单机热更新配置文件 2.环境 spri ...

  3. HITsz 数据库笔记

    这是 HITsz 数据库笔记,欢迎到我的 GitHub 上查看,有笔记说明和源码,作业和实验报告,希望对你有帮助 博客园显示图片异常 数据库基本概念 数据抽象 通过抽象来对用户屏蔽复杂性,以简化用户与 ...

  4. POJ2115C Looooops

    http://poj.org/problem?id=2115 k位储存特点,一旦溢出,那么就到第二个循环开始返回0重新计数.问题实际转化成a+cx=b(mod 2^k)跑多少圈能够重合.因为是k位无符 ...

  5. 05.python解析式与生成器表达式

    解析式和生成器表达式 列表解析式 列表解析式List Comprehension,也叫列表推导式 #生成一个列表,元素0-9,将每个元素加1后的平方值组成新的列表 x = [] for i in ra ...

  6. JAVA-JDK1.7-ConCurrentHashMap-测试和验证

    概述 上次记录了关于ConCurrentHashMap的原理以及源码,现在我对其进行有关功能的测试,下面就讲解一下我测试的内容和代码.这些测试主要针对JDK1.7版本. GET安全测试 上一篇写过ge ...

  7. 【视频解码性能对比】opencv + cuvid + gpu vs. ffmpeg + cpu

    视频大小:1168856 字节画面尺寸:480*848帧数:275opencv + cuvid + tesla P4, 解码性能:1426.84 fps ffmpeg 4.0 API + [Intel ...

  8. ros实例_百度语音+图灵

    1 百度语音模块 参考http://blog.csdn.net/u011118482/article/details/55001444 1.1 百度语音识别包 git clonehttps://git ...

  9. C# Reflection反射机制

    一.反射 什么是反射 .Net的应用程序由几个部分:'程序集(Assembly)'.'模块(Module)'.'类型(class)'组成: 反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组 ...

  10. 科技爱好者周刊(第 176 期):中国法院承认 GPL 吗?

    这里记录每周值得分享的科技内容,周五发布. 本杂志开源(GitHub: ruanyf/weekly),欢迎提交 issue,投稿或推荐科技内容. 周刊讨论区的帖子<谁在招人?>,提供大量程 ...