[APIO2018]铁人两项——圆方树+树形DP
题目链接:
对于点双连通分量有一个性质:在同一个点双里的三个点$a,b,c$,一定存在一条从$a$到$c$的路径经过$b$且经过的点只被经过一次。
那么我们建出原图的圆方树,枚举中间点$b$,一对合法的$a,c$需要使这两个点位于与$b$直接相连的方点的不同子树中。树形$DP$,对圆点和方点分别统计答案即可。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n,m;
int x,y;
vector<int>q[200010];
int head[100010];
int to[400010];
int next[400010];
int size[200010];
int low[100010];
int dfn[100010];
int tot;
int cnt;
int num;
int st[100010];
int top;
int vis[200010];
ll ans;
int sum;
void add(int x,int y)
{
tot++;
next[tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void insert(int x,int y)
{
q[x].push_back(y);
}
void tarjan(int x)
{
st[++top]=x;
low[x]=dfn[x]=++num;
for(int i=head[x];i;i=next[i])
{
if(!dfn[to[i]])
{
tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
if(low[to[i]]>=dfn[x])
{
insert(++cnt,x);
insert(x,cnt);
int now=0;
do
{
now=st[top--];
insert(cnt,now);
insert(now,cnt);
}
while(now!=to[i]);
}
}
else
{
low[x]=min(low[x],dfn[to[i]]);
}
}
}
void dfs(int x,int fa)
{
vis[x]=1;
size[x]=(x<=n?1:0);
int len=q[x].size();
for(int i=0;i<len;i++)
{
int to=q[x][i];
if(to!=fa)
{
dfs(to,x);
size[x]+=size[to];
}
}
}
void tree_dp(int x,int fa)
{
int len=q[x].size();
for(int i=0;i<len;i++)
{
int to=q[x][i];
if(to!=fa)
{
tree_dp(to,x);
}
}
if(x<=n)
{
for(int i=0;i<len;i++)
{
int to=q[x][i];
if(to!=fa)
{
ans+=1ll*size[to]*(sum-size[to]-1);
}
else
{
ans+=1ll*(sum-size[x])*(size[x]-1);
}
}
}
else if(len>=3)
{
for(int i=0;i<len;i++)
{
int to=q[x][i];
if(to!=fa)
{
ans+=1ll*size[to]*(sum-size[to])*(len-2);
}
else
{
ans+=1ll*(sum-size[x])*size[x]*(len-2);
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);cnt=n;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
for(int i=1;i<=cnt;i++)
{
if(!vis[i])
{
dfs(i,0);
sum=size[i];
tree_dp(i,0);
}
}
printf("%lld",ans);
}
[APIO2018]铁人两项——圆方树+树形DP的更多相关文章
- loj2587 「APIO2018」铁人两项[圆方树+树形DP]
主要卡在一个结论上..关于点双有一个常用结论,也经常作为在圆方树/简单路径上的良好性质,对于任意点双内互不相同的三点$s,c,t$,都存在简单路径$s\to c\to t$,证明不会.可以参见clz博 ...
- [APIO2018]铁人两项 --- 圆方树
[APIO2018] 铁人两项 题目大意: 给定一张图,问有多少三元组(a,b,c)(a,b,c 互不相等)满足存在一条点不重复的以a为起点,经过b,终点为c的路径 如果你不会圆方树 ------- ...
- [APIO2018] Duathlon 铁人两项 圆方树,DP
[APIO2018] Duathlon 铁人两项 LG传送门 圆方树+简单DP. 不会圆方树的话可以看看我的另一篇文章. 考虑暴力怎么写,枚举两个点,答案加上两个点之间的点的个数. 看到题面中的一句话 ...
- [APIO2018]铁人两项 [圆方树模板]
把这个图缩成圆方树,把方点的权值设成-1,圆点的权值设成点双的size,算 经过这个点的路径的数量*这个点的点权 的和即是答案. #include <iostream> #include ...
- [BZOJ5463][APIO2018]铁人两项(圆方树DP)
题意:给出一张图,求满足存在一条从u到v的长度大于3的简单路径的有序点对(u,v)个数. 做了上一题[HDU5739]Fantasia(点双连通分量+DP),这个题就是一个NOIP题了. 一开始考虑了 ...
- 【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 路 ...
- 洛谷P4630 铁人两项--圆方树
一道很好的圆方树入门题 感谢PinkRabbit巨佬的博客,讲的太好啦 首先是构建圆方树的代码,也比较好想好记 void tarjan(int u) { dfn[u] = low[u] = ++dfn ...
- 2019.03.29 bzoj5463: [APIO2018] 铁人两项(圆方树+树形dp)
传送门 题意简述:给你一张无向图,问你满足存在从a−>b−>ca->b->ca−>b−>c且不经过重复节点的路径的有序点对(a,b,c)(a,b,c)(a,b,c) ...
随机推荐
- Python遗传和进化算法框架(一)Geatpy快速入门
https://blog.csdn.net/qq_33353186/article/details/82014986 Geatpy是一个高性能的Python遗传算法库以及开放式进化算法框架,由华南理工 ...
- VBA switch语句
当用户想要根据Expression的值执行一组语句时,使用Switch Case语句. 每个值被称为一个”情况”,并根据每种情况变量接通测试.如果测试表达式与用户指定的任何Case不匹配,则执行Cas ...
- 使用browser-sync预览pandoc markdown???
由于 pandoc markdown在sublime下面并不能很好的预览,因此可以直接 使用 pandoc build成html,然后借助下面的工具进行实时在浏览器里面预览 http://www.br ...
- Nginx的反向代理和负载均衡服务
Nginx (engine x) 是一个高性能的HTTP和反向代理服务,也是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行. ...
- 解决mysql登录警告问题
一.前言 我们在登录mysql的时候经常会看到一句警告: Warning: Using a password on the command line interface can be insecure ...
- Oracle死锁处理实例
Oracle死锁常规语句 1.查询Oracle死锁常规语句 SELECT l.session_id sid, s.serial#, l.locked_mode,l.oracle_username, l ...
- 他爬取了B站所有番剧信息,发现了这些……
本文来自「楼+ 之数据分析与挖掘实战 」第 4 期学员 -- Yueyec 的作业.他爬取了B站上所有的番剧信息,发现了很多有趣的数据- 关键信息:最高播放量 / 最强up主 / 用户追番数据 / 云 ...
- RT-Thread--线程间同步
线程间同步 一个线程从传感器中接收数据并且将数据写到共享内存中,同时另一个线程周期性的从共享内存中读取数据并发送去显示,下图描述了两个线程间的数据传递: 如果对共享内存的访问不是排他性的,那么各个线程 ...
- 使用Ultra Librarian工具生成Altium封装和原理图符号的方法
最近在项目中用到了TI的单通道SPDT 模拟开关TS5A3160芯片,Altium官方的库中没有该元件的封装库,所以需要自己画.Ti在官网的产品介绍中提供了生成原理图符号和 PCB 布局封装的方法. ...
- c++之:new与malloc
#include <iostream> using namespace std; void spacealloc_c() { //开辟内存空间---C语言风格 int *p = (int ...