正题

题目链接: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铁人两项【圆方树】的更多相关文章

  1. [APIO2018] Duathlon 铁人两项 圆方树,DP

    [APIO2018] Duathlon 铁人两项 LG传送门 圆方树+简单DP. 不会圆方树的话可以看看我的另一篇文章. 考虑暴力怎么写,枚举两个点,答案加上两个点之间的点的个数. 看到题面中的一句话 ...

  2. 【Luogu4630】【APIO2018】 Duathlon 铁人两项 (圆方树)

    Description ​ 给你一张\(~n~\)个点\(~m~\)条边的无向图,求有多少个三元组\(~(x, ~y, ~z)~\)满足存在一条从\(~x~\)到\(~z~\)并且经过\(~y~\)的 ...

  3. LOJ 2587 「APIO2018」铁人两项——圆方树

    题目:https://loj.ac/problem/2587 先写了 47 分暴力. 对于 n<=50 的部分, n3 枚举三个点,把图的圆方树建出来,合法条件是 c 是 s -> f 路 ...

  4. loj2587 「APIO2018」铁人两项[圆方树+树形DP]

    主要卡在一个结论上..关于点双有一个常用结论,也经常作为在圆方树/简单路径上的良好性质,对于任意点双内互不相同的三点$s,c,t$,都存在简单路径$s\to c\to t$,证明不会.可以参见clz博 ...

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

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

  6. 洛谷P4630 [APIO2018] Duathlon 铁人两项 (圆方树)

    圆方树大致理解:将每个点双看做一个新建的点(方点),该点双内的所有点(圆点)都向新建的点连边,最后形成一棵树,可以给点赋予点权,用以解决相关路径问题. 在本题中,方点点权赋值为该点双的大小,因为两个点 ...

  7. [APIO2018]铁人两项 --- 圆方树

     [APIO2018] 铁人两项 题目大意: 给定一张图,问有多少三元组(a,b,c)(a,b,c 互不相等)满足存在一条点不重复的以a为起点,经过b,终点为c的路径 如果你不会圆方树 ------- ...

  8. [APIO2018]铁人两项——圆方树+树形DP

    题目链接: [APIO2018]铁人两项 对于点双连通分量有一个性质:在同一个点双里的三个点$a,b,c$,一定存在一条从$a$到$c$的路径经过$b$且经过的点只被经过一次. 那么我们建出原图的圆方 ...

  9. [APIO2018]铁人两项 [圆方树模板]

    把这个图缩成圆方树,把方点的权值设成-1,圆点的权值设成点双的size,算 经过这个点的路径的数量*这个点的点权 的和即是答案. #include <iostream> #include ...

  10. 洛谷P4630 铁人两项--圆方树

    一道很好的圆方树入门题 感谢PinkRabbit巨佬的博客,讲的太好啦 首先是构建圆方树的代码,也比较好想好记 void tarjan(int u) { dfn[u] = low[u] = ++dfn ...

随机推荐

  1. The requested PHP extension ext-http * is missing from your system. Install or enable PHP's http ex

    composer.json 包含 "require": { "ext-http": "*" } 删掉  "ext-http&quo ...

  2. 五、Abp vNext 基础篇丨博客聚合功能

    介绍 业务篇章先从客户端开始写,另外补充一下我给项目起名的时候没多想起的太随意了,结果后面有些地方命名冲突了需要通过手动using不过问题不大. 开工 应用层 根据第三章分层架构里面讲到的现在我们模型 ...

  3. C#基础知识---迭代器与Foreach语句

    一.Foreach语句简介 在C# 1.0中我们经常使用foreach来遍历一个集合中的元素,然而如果一个集合要支持使用foreach语句来进行遍历,这个集合一般需要IEnumerable或IEnum ...

  4. git push&pull命令详解

    git pull的作用是从一个仓库或者本地的分支拉取并且整合代码. git pull [<options>] [<repository> [<refspec>-​] ...

  5. springMVC学习日志一

    一.springMVC流程图省略 二.写一个简单的springmvc的demo来说明 2.1引入springMVC相关的jar包 2.2配置DispatcherServlet 在web.xml < ...

  6. ARP协议工作原理实验

    一.实验目的 验证"在向目的主机发送数据包时会先查询ARP高速缓存,如果ARP高速缓存中已保存了目的主机的MAC地址,不进行ARP查询,使用ARP高速缓存中的MAC地址:如果缓存中没有IP对 ...

  7. default错误

    查看根目录发现 修改成index.php可以了

  8. Mybatis源码解析3——核心类SqlSessionFactory,看完我悟了

    这是昨晚的武汉,晚上九点钟拍的,疫情又一次来袭,曾经熙熙攘攘的夜市也变得冷冷清清,但比前几周要好很多了.希望大家都能保护好自己,保护好身边的人,生活不可能像你想象的那么好,但也不会像你想象的那么糟. ...

  9. mysqli的基本使用

    简单实例 面向过程方式 // 创建数据库连接 $connect = mysqli_connect('127.0.0.1', 'root', 'root', 'test', 8889); // 判读是否 ...

  10. 【算法】使用Golang实现加权负载均衡算法

    背景描述 如下图所示,负载均衡做为反向代理,将请求方的请求转发至后端的服务节点,实现服务的请求. 在nginx中可以通过upstream配置server时,设置weight表示对应server的权重. ...