洛谷P4630 [APIO2018] Duathlon 铁人两项 (圆方树)
圆方树大致理解:将每个点双看做一个新建的点(方点),该点双内的所有点(圆点)都向新建的点连边,最后形成一棵树,可以给点赋予点权,用以解决相关路径问题。
在本题中,方点点权赋值为该点双的大小,因为两个点双最多有一个交点,将圆点赋为-1来去重,先用tarjan()构建出圆方树,在跑一遍dfs,dfs枚举的是作为c的点,维护sz2[ ](圆点个数,因为s和f只能是圆点),利用乘法原理累加答案即可。
注意代码中累加答案是要乘2,(s和f可以交换)。
1 #include<bits/stdc++.h>
2 using namespace std;
3 const int N=500010;
4 typedef long long ll;
5
6 struct node{
7 int head[N],nxt[N<<1],to[N<<1],tot;
8 void add(int u,int v){
9 nxt[++tot]=head[u];head[u]=tot;to[tot]=v;
10 nxt[++tot]=head[v];head[v]=tot;to[tot]=u;
11 }
12 }G1,G2;
13 int dfn[N],low[N],st[N],sz[N],top,idx,tot,n,m,t1,t2,sznow;
14 //sznow存树中圆点个数
15 void tarjan(int u){//建立圆方树
16 sz[u]=-1;++sznow;
17 dfn[u]=low[u]=++tot;
18 st[++top]=u;//入栈
19 for(int i=G1.head[u];i;i=G1.nxt[i]){
20 if(!dfn[G1.to[i]]){
21 tarjan(G1.to[i]);
22 low[u]=min(low[u],low[G1.to[i]]);
23 if(dfn[u]<=low[G1.to[i]]){
24 ++idx;
25 int v;
26 do{
27 v=st[top--];
28 G2.add(v,idx);
29 ++sz[idx];
30 }while(v!=G1.to[i]);
31 ++sz[idx];
32 G2.add(u,idx);
33 //将该点双看做一个点,内部的点向该点连边
34 }
35 }
36 else low[u]=min(low[u],dfn[G1.to[i]]);
37 }
38 }
39
40 ll ans;
41 int sz2[N];
42
43 void dfs(int u,int fa){
44 sz2[u]=u<=n; //只有圆点才可作为s或f,c在圆点方点都行
45 for(int i=G2.head[u],v;i;i=G2.nxt[i]){
46 if((v=G2.to[i])!=fa){//计算子树两两积
47 dfs(v,u);
48 ans+=2ll*sz2[u]*sz2[v]*sz[u];
49 sz2[u]+=sz2[v];
50 }
51 }
52 ans+=2ll*sz2[u]*(sznow-sz2[u])*sz[u];
53 }
54
55 int main(){
56 scanf("%d%d",&n,&m);
57 idx=n;
58 for(int i=1;i<=m;i++){
59 scanf("%d%d",&t1,&t2);
60 G1.add(t1,t2);
61 }
62 for(int i=1;i<=n;i++){
63 if(!dfn[i]){//对于每个连通块都要先清空
64 sznow=0;
65 top=0;
66 tarjan(i);
67 dfs(i,0);
68 }
69 }
70 printf("%lld\n",ans);
71 }
洛谷P4630 [APIO2018] Duathlon 铁人两项 (圆方树)的更多相关文章
- [APIO2018] Duathlon 铁人两项 圆方树,DP
[APIO2018] Duathlon 铁人两项 LG传送门 圆方树+简单DP. 不会圆方树的话可以看看我的另一篇文章. 考虑暴力怎么写,枚举两个点,答案加上两个点之间的点的个数. 看到题面中的一句话 ...
- 洛谷P4630 [APIO2018] Duathlon 铁人两项 【圆方树】
题目链接 洛谷P4630 题解 看了一下部分分,觉得树的部分很可做,就相当于求一个点对路径长之和的东西,考虑一下能不能转化到一般图来? 一般图要转为树,就使用圆方树呗 思考一下发现,两点之间经过的点双 ...
- [洛谷P4630][APIO2018] Duathlon 铁人两项
题目大意:给一张无向图,求三元组$(u,v,w)$满足$u->v->w$为简单路径,求个数 题解:圆方树,缩点后$DP$,因为同一个点双中的点一定地位相同 卡点:1.$father$数组开 ...
- 【Luogu4630】【APIO2018】 Duathlon 铁人两项 (圆方树)
Description 给你一张\(~n~\)个点\(~m~\)条边的无向图,求有多少个三元组\(~(x, ~y, ~z)~\)满足存在一条从\(~x~\)到\(~z~\)并且经过\(~y~\)的 ...
- LOJ 2587 「APIO2018」铁人两项——圆方树
题目:https://loj.ac/problem/2587 先写了 47 分暴力. 对于 n<=50 的部分, n3 枚举三个点,把图的圆方树建出来,合法条件是 c 是 s -> f 路 ...
- loj2587 「APIO2018」铁人两项[圆方树+树形DP]
主要卡在一个结论上..关于点双有一个常用结论,也经常作为在圆方树/简单路径上的良好性质,对于任意点双内互不相同的三点$s,c,t$,都存在简单路径$s\to c\to t$,证明不会.可以参见clz博 ...
- 洛谷P4630 铁人两项--圆方树
一道很好的圆方树入门题 感谢PinkRabbit巨佬的博客,讲的太好啦 首先是构建圆方树的代码,也比较好想好记 void tarjan(int u) { dfn[u] = low[u] = ++dfn ...
- P4630 [APIO2018] Duathlon 铁人两项
思路 圆方树,一个点双中的所有点都可以被经过,所以给圆点赋值-1,方点赋值为圆点个数,统计圆点两两之间的路径权值和即可 代码 #include <cstdio> #include < ...
- [APIO2018]铁人两项 --- 圆方树
[APIO2018] 铁人两项 题目大意: 给定一张图,问有多少三元组(a,b,c)(a,b,c 互不相等)满足存在一条点不重复的以a为起点,经过b,终点为c的路径 如果你不会圆方树 ------- ...
随机推荐
- React报错之Cannot find name
正文从这开始~ .tsx扩展名 为了在React TypeScript中解决Cannot find name报错,我们需要在使用JSX文件时使用.tsx扩展名,在你的tsconfig.json文件中把 ...
- Apache DolphinScheduler 使用文档(7/8):系统参数及自定义参数
本文章经授权转载,原文链接: https://blog.csdn.net/MiaoSO/article/details/104770720 目录 7. 参数 7.1 系统参数 7.2 时间自定义参数 ...
- ajax初识
Ajax 全称为:"Asynchronous JavaScript and XML"(异步 JavaScript 和 XML) 它并不是 JavaScript 的一种单一技术,而是 ...
- FPGA/Verilog 资源整理
verilog学习教程(以Vivado为载体)https://vlab.ustc.edu.cn/guide/index.html 中科大的数电实验网站https://vlab.ustc.edu.cn/
- Luogu1088 火星人 (康托展开)
皮一波 #include <iostream> #include <cstdio> #include <cstring> #include <algorith ...
- 【java】学习路线14-抽象类、多态
/*抽象类 abstractabstract class A{ }注意abstract类中不一定需要有abstract方法但是有abstract方法的类中,该类一定是abstract方法抽象类不 ...
- Redis图形化管理工具
一.treeNMS Redis做为现在web应用开发的黄金搭担组合,工作中的项目大量使用了Redis,treeNMS是一款用于JAVA语言开发的Redis管理工具:treeNMS管理工具,直接到htt ...
- django_day09_项目相关
django_day09_项目相关 展示数据: 给模板一个querySet对象列表,循环出对象列表obj 普通字段 obj.字段名 ----> 数据库中的数据 外键 obj.外键 ------- ...
- 离线方式安装高可用RKE2 (版本: v1.22.13+rke2r1)记录
说明: 想要了解RKE2可以到官网(https://docs.rke2.io 或 https://docs.rancher.cn/docs/rke2/_index/)看最新资料 用官网给出的离线安装( ...
- Ubuntu系统apt添加第三方PPA源
一.前言 1.1目的 在使用Ubuntu时往往apt源会自带很多常用软件,但是大部分都是比较老的版本,本文主要是为了实现以下两个目的: 通过添加第三方的PPA源解决软件版本过低或者没有安装包的情况: ...