Description

​ 给你一张\(~n~\)个点\(~m~\)条边的无向图,求有多少个三元组\(~(x, ~y, ~z)~\)满足存在一条从\(~x~\)到\(~z~\)并且经过\(~y~\)的路径。保证两点之间最多只有一条边连接。

Solution

​ 考虑对这张图建圆方树,每个方点的权值记录该点双的点数,每个圆点的权值为\(-1\)。这样先确定\(~x, ~z~\)之后, 其路径上的点权和就是满足条件的\(~y~\)的个数 (因为一个圆点的贡献会算进两个相邻的方点中,所以每个圆点的权值是\(-1\)).

​ 现在考虑优化这个思路,可以发现每个点的点权对答案的贡献次数是该点出现在合法路径上出现的次数,所以可以\(~O(n)~\)快速求出该点的出现总次数。注意图不一定联通,\(~sum~\)为该联通块的大小。

\[Ans_u = val[u] \times [(sum - siz[u]) \times siz[u] + \sum_{v = son_x} siz[v] \times (siz[u] - siz[v])]
\]

Code

#include<bits/stdc++.h>
#define Set(a, b) memset(a, b, sizeof (a))
#define For(i, j, k) for(int i = j; i <= k; ++i)
#define Forr(i, j, k) for(int i = j; i >= k; --i)
#define Travel(i, u, G) for(int i = G.beg[u], v = G.to[i]; i; i = G.nex[i], v = G.to[i])
using namespace std; inline int read() {
int x = 0, p = 1; char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') p = -1;
for(; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x *= p;
} template<typename T> inline bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; } inline void File() {
#ifndef ONLINE_JUDGE
freopen("P4630.in", "r", stdin);
freopen("P4630.out", "w", stdout);
#endif
} typedef long long ll;
const int N = 2e5 + 10, M = N << 2;
int n, m, cnt, dfn[N], low[N], val[N], u, v, fa[N], clk, siz[N], sum, vis[N];
struct edge {
int e = 1, beg[N], nex[M], to[M];
inline void add(int x, int y) { to[++ e] = y, nex[e] = beg[x], beg[x] = e; }
} G1, G2;
stack<int> S; ll ans; inline void tarjan(int u, int f) {
dfn[u] = low[u] = ++ clk, S.push(u);
++ sum, val[u] = -1;
Travel(i, u, G1) if (v != f) {
if (!dfn[v]) {
tarjan(v, u), chkmin(low[u], low[v]);
if (low[v] >= dfn[u]) {
++ val[++ cnt], fa[cnt] = u, G2.add(u, cnt);
while (!S.empty()) {
int x = S.top(); S.pop();
G2.add(cnt, x), fa[x] = cnt, ++ val[cnt];
if (x == v) break;
}
}
} else chkmin(low[u], dfn[v]);
}
} inline void dfs(int u) {
if (u <= n) siz[u] = 1, vis[u] = 1;
ll res = 0;
Travel(i, u, G2) {
dfs(v), siz[u] += siz[v];
res += 2ll * siz[v] * (siz[u] - siz[v]);
}
res += 2ll * (sum - siz[u]) * (siz[u]);
ans += res * val[u];
} int main() {
File();
cnt = n = read(), m = read();
For(i, 1, m) u = read(), v = read(), G1.add(u, v), G1.add(v, u);
For(i, 1, n) if (!vis[i]) sum = 0, tarjan(i, 0), dfs(i);
cout << ans << endl;
return 0;
}

【Luogu4630】【APIO2018】 Duathlon 铁人两项 (圆方树)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. [BZOJ5463][APIO2018]铁人两项(圆方树DP)

    题意:给出一张图,求满足存在一条从u到v的长度大于3的简单路径的有序点对(u,v)个数. 做了上一题[HDU5739]Fantasia(点双连通分量+DP),这个题就是一个NOIP题了. 一开始考虑了 ...

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

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

随机推荐

  1. Luogu4199 万径人踪灭 FFT、Manacher

    传送门 先不考虑”不是连续的一段“这一个约束条件.可以知道:第$i$位与第$j$位相同,可以对第$\frac{i+j}{2}$位置上产生$1$的贡献(如果$i+j$为奇数表明它会对一条缝产生$1$的贡 ...

  2. Luogu3760 TJOI2017 异或和 树状数组

    传送门 题意:给出一个长度为$N$的非负整数序列,求其中所有连续区间的区间和的异或值.$N \leq 10^5$,所有元素之和$\leq 10^6$ 设序列的前缀和为$s_i$,特殊地,$s_0=0$ ...

  3. LiveCharts文档-1前言

    原文:LiveCharts文档-1前言 LiveCharts文档-1前言 最近做一个企业应用,客户端使用的是WPF,需要生成一个漂亮的统计图表,以前WinForm有Chart控件,但是微软貌似没有弄W ...

  4. Luogu P3374 【模板】树状数组 1

    真正的模板题. 树状数组的思想很简单(不如说背代码更简单),每个节点记录多个节点的信息(每个点存x&(-x)个). 道理可以参见很多大佬的博客,最后前缀和的思想搞一下就好了.不想说也不会说. ...

  5. 蓝牙 link timeout分析

    蓝牙主机和蓝牙设备建立连接之后,会在l2cap 层面上建立相应的channel,这些channel 基本上是用于各种不同的profile 或者protocol 进行通信用的. 当相应的profile或 ...

  6. C#_图片存取数据库Winform

    #region 用于在PictureBox控件中显示选择的图片        /// <summary>        /// 用于在PictureBox控件中显示选择的图片        ...

  7. M2postmortem

    设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 答:我们的软件主要解决信息提取的问题.定义清晰:要提取的内容包括于计算机科学相关内容的标题.作者. ...

  8. Linux内核分析第三周学习总结

    Linux内核源码简介 arch/ 该目录中包含和硬件体系结构相关的代码,每种平台占一个相应的目录. 和32位PC相关的代码存放在x86目录下. 每种平台至少包含3个子目录:kernel(存放支持体系 ...

  9. 结构化分析(SA)

    1.什么叫模型?我觉得它的关键字:抽象 重要特征 降低复杂度. 2.软件设计的方法 分类:面向功能~,面向对象的设计. 面向数据流的方法是在结构化分析中提到的. 哦~ 3.面向数据流的结构化分析 特点 ...

  10. 小学四则运算APP 第一阶段冲刺

    需求分析 1.相关系统分析员向用户初步了解需求,然后用word列出要开发的系统的大功能模块,每个大功能模块有哪些小功能模块,对于有些需求比较明确相关的界面时,在这一步里面可以初步定义好少量的界面.[1 ...