首先对于给出的图建立圆方树,然后我们分类讨论每一个点作为中间的中转站出现的情况有多少种,累积到 \(ans\) 中。

  对于圆点:在任意两个子树内分别选出一个节点都是合法的。

  对于方点:连接向方点的点均为处于一个双联通分量中的点,彼此之间两两可。所以若我们让这个双联通分量上的一个点作为中转站,在其他任意的两棵子树内挑出两个点来都是合法的。这样乍一看好像是 \(n^{2}\) 的统计方法,我们不妨改变一下:因为答案是累加起来的,我们分别考虑每一棵子树对于答案造成的贡献。这一棵子树中的点可以和另一棵子树内的点任意匹配选出两个,对于不在这两棵子树内的双联通分量上的点均产生有贡献。然后就可以愉快的 \(O(n)\) 统计啦~

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 500000
int N, n, m, tot, S[maxn], fa[maxn];
int timer, dfn[maxn], low[maxn];
int ans, size[maxn], cnt[maxn];
bool vis[maxn]; struct edge
{
int cnp = , head[maxn], to[maxn], last[maxn];
void add(int u, int v)
{
if(u == v) return;
to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;
to[cnp] = u, last[cnp] = head[v], head[v] = cnp ++;
}
}E1, E2, E3; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} void Tarjan(int u)
{
dfn[u] = low[u] = ++ timer; S[++ S[]] = u;
for(int i = E1.head[u]; i; i = E1.last[i])
{
int v = E1.to[i];
if(!dfn[v])
{
Tarjan(v); low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u])
{
E2.add(++ N, u); cnt[N] ++, cnt[u] ++; int x = ;
do
{
E2.add(N, x = S[S[] --]); cnt[N] ++, cnt[x] ++;
}while(x != v);
}
}
else low[u] = min(low[u], dfn[v]);
}
} void dfs(int u)
{
vis[u] = ;
if(u <= n) size[u] ++;
for(int i = E2.head[u]; i; i = E2.last[i])
{
int v = E2.to[i]; if(v == fa[u]) continue;
fa[v] = u; dfs(v); size[u] += size[v];
}
} void DP(int u)
{
for(int i = E2.head[u]; i; i = E2.last[i])
{
int v = E2.to[i]; if(v == fa[u]) continue;
DP(v);
}
int tem = ;
if(u <= n)
{
for(int i = E2.head[u]; i; i = E2.last[i])
{
int v = E2.to[i];
if(v != fa[u]) tem += (size[v]) * (tot - size[v] - );
else tem += (tot - size[u]) * (size[u] - );
}
}
else
{
if(cnt[u] > )
{
for(int i = E2.head[u]; i; i = E2.last[i])
{
int v = E2.to[i];
if(v != fa[u]) tem += (size[v]) * (tot - size[v]) * (cnt[u] - );
else tem += (tot - size[u]) * (size[u]) * (cnt[u] - );
}
}
}
ans += tem;
} signed main()
{
N = n = read(), m = read();
for(int i = ; i <= m; i ++)
{
int u = read(), v = read();
E1.add(u, v);
}
for(int i = ; i <= n; i ++)
if(!dfn[i]) Tarjan(i);
for(int i = ; i <= N; i ++)
if(!vis[i])
{
dfs(i); tot = size[i];
DP(i);
}
printf("%lld\n", ans);
return ;
}

【题解】APIO2018 Duathlon 铁人两项的更多相关文章

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

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

  2. [Luogu4630][APIO2018]Duathlon 铁人两项

    luogu 题目描述 比特镇的路网由 \(m\) 条双向道路连接的 \(n\) 个交叉路口组成. 最近,比特镇获得了一场铁人两项锦标赛的主办权.这场比赛共有两段赛程:选手先完成一段长跑赛程,然后骑自行 ...

  3. P4630 [APIO2018] Duathlon 铁人两项

    思路 圆方树,一个点双中的所有点都可以被经过,所以给圆点赋值-1,方点赋值为圆点个数,统计圆点两两之间的路径权值和即可 代码 #include <cstdio> #include < ...

  4. [APIO2018] Duathlon 铁人两项

    不经过重点,考虑点双 点双,考虑圆方树 两个点s,t,中间路径上,所有点双里的点都可以经过,特别地,s,t作为割点的时候,不能往后走,也就是不能经过身后的方点 也就是,(s,t)经过树上路径上的所有圆 ...

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

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

  6. [洛谷P4630][APIO2018] Duathlon 铁人两项

    题目大意:给一张无向图,求三元组$(u,v,w)$满足$u->v->w$为简单路径,求个数 题解:圆方树,缩点后$DP$,因为同一个点双中的点一定地位相同 卡点:1.$father$数组开 ...

  7. luogu 4630 [APIO2018] Duathlon 铁人两项

    题目大意: 无向图上找三个点 a b c使存在一条从a到b经过c的路径 求取这三个点的方案数 思路: 建立圆方树 这个圆方树保证没有两个圆点相连或两个方点相连 对于每个节点x 设该节点为路径的中间节点 ...

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

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

  9. 【APIO2018】铁人两项(圆方树,动态规划)

    [APIO2018]铁人两项(圆方树,动态规划) 题面 UOJ 洛谷 BZOJ 题解 嘤嘤嘤,APIO的时候把一个组合数写成阶乘了,然后这题的70多分没拿到 首先一棵树是很容易做的,随意指定起点终点就 ...

随机推荐

  1. Ceres优化

    Ceres Solver是谷歌2010就开始用于解决优化问题的C++库,2014年开源.在Google地图,Tango项目,以及著名的SLAM系统OKVIS和Cartographer的优化模块中均使用 ...

  2. 说说Ruby中的Symbol类

    相信大多人在学习Ruby过程中,都被Symbol类型迷惑过.因为其他语言基本没有这个类.而且它太灵活了.很多人只知其一不知其二. 本人查了不少资料,自己总结一下. 首先来看一下Ruby之父所著的< ...

  3. 四、新时间日期API

    一.使用 LocalDate .LocalTime .LocalDateTime LocalDate.LocalTime.LocalDateTime 类的实例是不可变的对象,分别表示使用 ISO-86 ...

  4. Ceph性能优化

    几个 Ceph 性能优化的新方法和思路(2015 SH Ceph Day 参后感) 一周前,由 Intel 与 Redhat 在10月18日联合举办了 Shanghai Ceph Day.在这次会议上 ...

  5. WeTest功能优化第1期:截图960px,云真机映射功能了解

    第1期功能优化目录 [全线产品测试截图优化]安卓机型测试截图分辨率上升至960px [云真机新增Android 9]最新安卓系统,等你pick [云真机新增键盘映射功能]电脑键盘码字,云真机同步显示  ...

  6. Python Road

    引子 雁离群兮不知所归,路遥远兮吾将何往   Python Road[第一篇]:Python简介 Python Road[第二篇]:Python基本数据类型 Python Road[第三篇]:Pyth ...

  7. Windows运行机理——API与SDK

    Windows运行机理这系列文章都是来至于<零基础学Qt4编程>——吴迪,个人觉得写得很好,所以搬运加以整理. 首先 API:Application Programmaing Interf ...

  8. GIt学习第二天之版本回退、工作区和暂存区

    搬运自 ‘廖雪峰的官方网站’ 地址:https://www.liaoxuefeng.com/ 1.版本回退 在Git中,我们用git log命令显示从最近到最远的提交日志,如果嫌输出信息太多,看得眼花 ...

  9. CSS3自定义字体

    原文摘自:https://www.cnblogs.com/moqiutao/archive/2015/12/23/5070463.html 总节: 1) 定义字体标准格式: @font-face { ...

  10. Sql server在cmd下的使用

    方法一 在DOS提示符下,c:\>isql -U sa -P (此处输入SA密码) 注----大小写敏感 回车后会出现"1>"提示符,表明已成功,此时可在DOS下做任何 ...