P4630-[APIO2018]Duathlon铁人两项【圆方树】
正题
题目链接:https://www.luogu.com.cn/problem/P4630
题目大意
\(n\)个点\(m\)条边的一张无向图,求有多少对三元组\((s,c,f)\)满足\(s\neq f\neq t\)且存在一条从\(s\)到\(f\)的简单路径经过\(c\)
解题思路
一个比较显然的结论是在一个点双中的三个点\((a,b,c)\)那么必然存在一条\(a\)到\(b\)的简单路径经过\(c\)。因为一定存在两条不交的\(a->c\)和\(c->b\)的路径,那么如果一条\(a->c\)和\(c->b\)的路径交了,那么另一条就一定不交。
然后从一个点双出来后就不能再回到这个点双了,所以我们可以考虑在圆方树上做这个问题。
设定义圆点的权值为\(-1\),方点的权值为连接的圆点数量,这样我们在圆方树上走的时候就可以固定经过进入和离开这个点双的点了。
然后问题就变为了求每条圆点之间路径的点权和的和。
用树形\(dp\)搞就好了,时间复杂度\(O(n)\)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
const int N=2e5+10;
int n,m,num,cnt,dfc,w[N];
int low[N],dfn[N],siz[N];
vector<int> G[N],T[N];
stack<int> s;
long long ans;
void tarjan(int x){
dfn[x]=low[x]=++dfc;
w[x]=-1;s.push(x);num++;
for(int y:T[x])
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(dfn[x]==low[y]){
++cnt;int k;
do{
k=s.top();
G[cnt].push_back(k);
G[k].push_back(cnt);
w[cnt]++;s.pop();
}while(k!=y);
G[cnt].push_back(x);
G[x].push_back(cnt);
w[cnt]++;
}
}
else low[x]=min(low[x],dfn[y]);
return;
}
void solve(int x,int fa){
siz[x]=(x<=n);
for(int y:G[x]){
if(y==fa)continue;
solve(y,x);
ans+=2ll*siz[y]*siz[x]*w[x];
siz[x]+=siz[y];
}
ans+=2ll*siz[x]*(num-siz[x])*w[x];
return;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y;scanf("%d%d",&x,&y);
T[x].push_back(y);
T[y].push_back(x);
}
cnt=n;
for(int i=1;i<=n;i++)
if(!dfn[i]){
num=0;
tarjan(i);
solve(i,0);
}
printf("%lld\n",ans);
return 0;
}
P4630-[APIO2018]Duathlon铁人两项【圆方树】的更多相关文章
- [APIO2018] Duathlon 铁人两项 圆方树,DP
[APIO2018] Duathlon 铁人两项 LG传送门 圆方树+简单DP. 不会圆方树的话可以看看我的另一篇文章. 考虑暴力怎么写,枚举两个点,答案加上两个点之间的点的个数. 看到题面中的一句话 ...
- 【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 [APIO2018] Duathlon 铁人两项 【圆方树】
题目链接 洛谷P4630 题解 看了一下部分分,觉得树的部分很可做,就相当于求一个点对路径长之和的东西,考虑一下能不能转化到一般图来? 一般图要转为树,就使用圆方树呗 思考一下发现,两点之间经过的点双 ...
- 洛谷P4630 [APIO2018] Duathlon 铁人两项 (圆方树)
圆方树大致理解:将每个点双看做一个新建的点(方点),该点双内的所有点(圆点)都向新建的点连边,最后形成一棵树,可以给点赋予点权,用以解决相关路径问题. 在本题中,方点点权赋值为该点双的大小,因为两个点 ...
- [APIO2018]铁人两项 --- 圆方树
[APIO2018] 铁人两项 题目大意: 给定一张图,问有多少三元组(a,b,c)(a,b,c 互不相等)满足存在一条点不重复的以a为起点,经过b,终点为c的路径 如果你不会圆方树 ------- ...
- [APIO2018]铁人两项——圆方树+树形DP
题目链接: [APIO2018]铁人两项 对于点双连通分量有一个性质:在同一个点双里的三个点$a,b,c$,一定存在一条从$a$到$c$的路径经过$b$且经过的点只被经过一次. 那么我们建出原图的圆方 ...
- [APIO2018]铁人两项 [圆方树模板]
把这个图缩成圆方树,把方点的权值设成-1,圆点的权值设成点双的size,算 经过这个点的路径的数量*这个点的点权 的和即是答案. #include <iostream> #include ...
- 洛谷P4630 铁人两项--圆方树
一道很好的圆方树入门题 感谢PinkRabbit巨佬的博客,讲的太好啦 首先是构建圆方树的代码,也比较好想好记 void tarjan(int u) { dfn[u] = low[u] = ++dfn ...
随机推荐
- ffmpeg第2篇:简单滤镜与复杂滤镜的区别
在ffmpeg的滤镜中,有简单滤镜(simple filter)和复杂滤镜(complex filter)两种. 使用简单滤镜时,用-vf选项,使用复杂滤镜时,使用-filter_complex或-l ...
- 使用F#编写PowerShell模块
▲F#和PowerShell模块 作为可能是人类世界最强大的Shell,PowerShell最大的特点是能够直接在命令间传递.NET对象,而支持这种能力的命令被称作cmdlet.自己编写PowerSh ...
- js 遍历数组对象求和
这个通常是求多个商品的总价遇到的情形: [ 0: {id: 1, name: "服务费", price: "1.00"} 1: {id: 2, name: &q ...
- C#调用C++ dll中返回值为字符串的函数问题
C#调用C++ dll函数,如果返回值为字符串,我们使用string去接收就会报错,因为C++返回的是char*,是个指针,所以c# 要用 IntPtr 来接收. C++: //预编译的标头 .h e ...
- C# 读取保存xml文件
直接读取xml文件中的内容 XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(result); XmlNode root = xmlDoc. ...
- 【C语言】第4章 选择结构程序设计
第4章 选择结构程序设计 C语言有两种选择语句: if 语句,实现两个分支的选择结构 switch 语句,实现多分支的选择结构 输入3个数a,b,c,要求按由小到大的顺序输出. 可以先用伪代码写出算法 ...
- nginx 开启,关闭,重启
2021-08-191. 启动 # 判断配置文件是否正确 cd /usr/local/nginx/sbin ./nginx -t # 启动 cd usr/local/nginx/sbin ./ngin ...
- 提交Spark作业遇到的NoSuchMethodError问题总结
测试应用说明 测试的Spark应用实现了同步hive表到kafka的功能.具体处理流程: 从 ETCD 获取 SQL 语句和 Kafka 配置信息 使用 SparkSQL 读取 Hive 数据表 把 ...
- Tars | 第3篇 Tars中期汇报测试文档(Java语言实现Subset路由规则)
目录 前言 1. 任务介绍 2. 测试模拟方案 2.0 *前置工作 2.1 添加路由规则 2.2 添加存活节点 2.3 [输出]遍历输出当前存活节点 2.4 [核心]对存活节点按subset规则过滤 ...
- Linux下cat命令的使用
1.普通用法-->查看文件内容 cat file_name 查看文件时的相关参数: 1.cat f1.txt,查看f1.txt文件的内容. 2.cat -n f1.txt,查看f1.txt文件的 ...