【APIO 2018】铁人两项(圆方树)
2018-07-18 08:19
330 查看
题意大概是,求有多少三元组$(s,c,f)(s \neq c, c \neq f, s \neq f)$,满足从$s$到$f$有一条简单路径经过$c$。
得到结论:
- 点双中任意互不相同的三个点,必定存在一条简单路径依次经过这三个点。
- 显然,割点只能经过一次。
建出一棵圆方树,圆点的权值为$-1$,方点的权值为该点双中点的个数,那任意两个圆点之间可以作为它们中转点的个数就是它们在圆方树上路径的点权和。
具体来讲就是割点上只能经过一次,圆点设成$-1$是为了去重方便。
以前只写过点双缩树,这里写圆方树更方便,权且将这道题作为学习的例题吧。
建圆方树只要在Tarjan上稍作修改,这里给出建树的例子:
#include <cstdio> #include <vector> #include <iostream> typedef long long LL; const int N = 200005; int n, m; int dfn , low , in , siz , sta , top, _clock, c_n; std::vector<int> xtr ; LL ans, sum ; int yun = 1, las , to[N << 1], pre[N << 1]; inline void Add(int a, int b) { to[++yun] = b; pre[yun] = las[a]; las[a] = yun; } void Tarjan(int x, int fa) { sta[++top] = x; in[x] = -1; dfn[x] = low[x] = ++_clock; for (int i = las[x]; i; i = pre[i]) { if (to[i] == fa) continue; if (dfn[to[i]]) { low[x] = std::min(low[x], dfn[to[i]]); } else { Tarjan(to[i], x); low[x] = std::min(low[x], low[to[i]]); if (dfn[x] <= low[to[i]]) { xtr[x].push_back(++c_n); ++in[c_n]; for (int t = -1; t != to[i]; ) { t = sta[top--]; xtr[c_n].push_back(t); ++in[c_n]; } } } } } void Dfs(int x) { if (in[x] < 0) siz[x] = 1, sum[x] = in[x]; for (int i = 0; i < (int)xtr[x].size(); ++i) { int v = xtr[x][i]; Dfs(v); siz[x] += siz[v]; sum[x] += (LL) siz[v] * in[x] + sum[v]; } } void Calc(int x) { if (in[x] < 0) ans += sum[x] - in[x]; LL cnt = 0; for (int i = 0; i < (int)xtr[x].size(); ++i) { int v = xtr[x][i]; ans += (LL) sum[v] * (siz[x] - (in[x] < 0) - siz[v]); cnt += (LL) siz[v] * (siz[x] - (in[x] < 0) - siz[v]); } ans += (LL) cnt / 2 * in[x]; for (int i = 0; i < (int)xtr[x].size(); ++i) { int v = xtr[x][i]; Calc(v); } } int main() { scanf("%d%d", &n, &m); c_n = n; for (int i = 1, x, y; 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, 0); Dfs(i); Calc(i); } } printf("%lld\n", ans * 2); return 0; }View Code
$\bigodot$技巧&套路:
- 圆方树的构建,圆方树上的统计技巧,可以用圆点的权值设成$-1$来去重。
相关文章推荐
- LOJ.2587.[APIO2018]铁人两项Duathlon(圆方树)
- [APIO2018]铁人两项(圆方树DP)
- LOJ2587:[APIO2018]铁人两项——题解
- 洛谷P4630 [APIO2018] Duathlon 铁人两项 【圆方树】
- [APIO2018] New Home 新家
- [APIO2018] Circle selection 选圆圈
- CTSC && APIO 2018划水记
- APIO 2018 游记
- CTSC2018 && APIO2018 游记
- 【LOJ】#2587. 「APIO2018」铁人两项
- [APIO2018]新家(线段树+堆)
- mobiquity Money获得GSMA GLOMO Awards 2018两项提名
- [APIO2018]选圆圈(KD-Tree)
- Codeforces Round #445 (Div. 2, based on Technocup 2018 Elimination Round 3)
- [APIO2015]雅加达的摩天楼
- 项目中使用的插件列表(2018稳定插件的是使用会增加2-3倍)
- sentos7安装idea2018
- 2017-2018-1 20155226《信息安全系统设计基础》第9周学习总结
- [BZOJ5285][HNOI2018]寻宝游戏
- 2017-2018-1 20155202 《信息安全系统设计基础》第9周学习总结