[APIO2018] Duathlon 铁人两项
时间:2022-01-24
本文章向大家介绍[APIO2018] Duathlon 铁人两项,主要包括[APIO2018] Duathlon 铁人两项使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
\(\text{Problem}\)
给定一张简单无向图,问有多少对三元组 \((s,c,f)\)(\(s,c,f\) 互不相同)使得存在一条简单路径从 \(s\) 出发,经过 \(c\) 到达 \(f\)。
\(\text{Solution}\)
很显然先建出圆方树,然后考虑 \((s,c,f)\) 存在的数量
我的一般想法是考虑固定 \(c\) 统计 \((s,f)\) 的数量
这确实用了树的性质,但没用到圆方树的性质,而且因为点双的讨论,使统计非常复杂
后来看了看正解,颇有一种如获至宝的感觉
考虑固定 \(s,f\) 统计 \(c\) 的数量,那就是 \(s\) 到 \(f\) 所有简单路径点的并集大小 \(-2\)(即除去 \(s,f\))
貌似也并不好弄,然而放到圆方树上就成了路径上圆点和方点所连的圆点的个数
于是不难想到将方点权值赋为与其相连圆点个数,圆点权值赋为 \(-1\)
\(s\) 到 \(f\) 所有简单路径点的并集大小即为路径上的点权和
统计的话,换种思考角度,变为统计一个点的点权的贡献,这就很简单了
\(\text{Code}\)
#include <cstdio>
#include <iostream>
#define RE register
#define IN inline
using namespace std;
typedef long long LL;
const int N = 2e5 + 5;
int n, m, cnt, top, tot1, tot2, dfc;
int val[N], h1[N], h2[N], low[N], dfn[N], siz[N], stk[N];
LL ans;
struct edge{int to, nxt;}e1[N * 5], e2[N * 5];
IN void add1(int x, int y){e1[++tot1] = edge{y, h1[x]}, h1[x] = tot1;}
IN void add2(int x, int y){e2[++tot2] = edge{y, h2[x]}, h2[x] = tot2;}
void Tarjan(int x)
{
dfn[x] = low[x] = ++dfc, stk[++top] = x, val[x] = -1;
for(RE int i = h1[x]; i; i = e1[i].nxt)
{
int v = e1[i].to;
if (!dfn[v])
{
Tarjan(v), low[x] = min(low[x], low[v]);
if (dfn[x] == low[v])
{
++cnt, add2(cnt, x), add2(x, cnt), ++val[cnt];
for(RE int u = 0; u ^ v; --top)
u = stk[top], add2(cnt, u), add2(u, cnt), ++val[cnt];
}
}
else low[x] = min(low[x], dfn[v]);
}
}
void Dfs(int x, int fa)
{
siz[x] = (x <= n);
for(RE int i = h2[x]; i; i = e2[i].nxt)
{
int v = e2[i].to;
if (v == fa) continue;
Dfs(v, x), ans += 2LL * val[x] * siz[v] * siz[x], siz[x] += siz[v];
}
ans += 2LL * val[x] * siz[x] * (dfc - siz[x]);
}
int main()
{
scanf("%d%d", &n, &m);
for(RE int i = 1, x, y; i <= m; i++) scanf("%d%d", &x, &y), add1(x, y), add1(y, x);
cnt = n;
for(RE int rt = 1; rt <= n; rt++)
if (!dfn[rt]) top = dfc = 0, Tarjan(rt), Dfs(rt, 0);
printf("%lld\n", ans);
}
原文地址:https://www.cnblogs.com/leiyuanze/p/15840773.html
- 6个编写优质干净代码的技巧
- 【Jfinal源码】第一章 com.jfinal.core.JFinalFilter(1)
- 【ehcache】 timeToLiveSeconds 和 timeToLiveSeconds 的区别
- 升级 CentOS7 、Redis 3.2.x 的问题
- AngularJS 中使用Swiper制作滚动图不能滑动
- JAVA服务端配置允许跨域请求
- CentOS mysql配置主从复制
- Quartz依赖数据库表
- Spring Security Oauth2.0 实现短信验证码登录
- 【Spring Cloud】Redis缓存接入监控、运维平台CacheCloud
- 基于Redis实现分布式应用限流
- Jasypt : 整合spring boot加密应用配置文件敏感信息
- Eureka:扩展ClientFilter实现服务注册自定义过滤
- 【系统日志】log4j配置学习总结
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- linux中alarm函数的实例讲解
- 如何给Linux虚拟机连上WiFi详解
- Linux系统查看CPU、机器型号、内存等信息
- 实战基本的Linux sed命令示例代码
- 在Linux中如何查看可用的网络接口详解
- Linux程序运行时加载动态库失败的解决方法
- Linux/CentOS系统同步网络时间的2种方法详解
- Linux 常用命令之Linux more命令使用方法
- Ubuntu下VIM配置成C++开发编辑器
- Ubuntu环境下使用G++编译CPP文件
- Linux下Tomcat的几种运行方式讲解
- linux中chmod命令用法详解
- Linux强制释放占用端口以及Linux防火墙端口开放方法详解
- CentOS7.5从零安装Python3.6.6的教程详解
- 实现一台或者多台Linux实例解绑SSH密钥对