题解

学习了圆方树!(其实是复习了Tarjan求点双)

我又双叒叕忘记了tarjan点双一个最重要,最重要的事情!

就是……假如low[v] >= dfn[u],我们就找到了一个点双,开始建立方点,但是,虽然这个点双包括点u,然而这个u啊,它很花心可能会在很多个点双里!首先u,不能被弹出去

其次呢,在栈里,u和这个点双其他的点,在栈里不一定是连续的一段,一般都是 u (一堆别的点) 点双里的点……,所以我们弹出到v,就结束这个点双,然后手动把u加进去

然后我们再来看这道题,我们枚举两个点,起点和终点,能当做中转点的点,一定是路上经过的点双里点的和

那么我们把所有点的值设成-1,方点的值设成点双里点的个数,然后就变成了对圆方树上所有路径统计路径长度,一个优秀做法就是枚举每个点看看会被多少条路径经过

代码

#include <iostream>
#include <cstdio>
#include <vector>
//#define ivorysi
#define pb push_back
#define MAXN 100005
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) putchar('-');
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
struct node {
int to,next;
}E[MAXN * 4];
int N,M,Cnt;
int head[MAXN],sumE,S;
int low[MAXN],dfn[MAXN],idx,sta[MAXN],top,tot,Val[MAXN * 4],siz[MAXN * 4];
int64 ans = 0;
vector<int> son[MAXN * 4];
void add(int u,int v) {
E[++sumE].to = v;
E[sumE].next = head[u];
head[u] = sumE;
}
void Tarjan(int u,int fa) {
dfn[u] = low[u] = ++idx;
sta[++top] = u;
Val[u] = -1;
siz[u] = 1;
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(dfn[v] && v != fa) {
low[u] = min(dfn[v],low[u]);
}
else if(!dfn[v]) {
Tarjan(v,u);
if(low[v] >= dfn[u]) {
++Cnt;
son[u].pb(Cnt);
while(1) {
int x = sta[top--];
Val[Cnt]++;
son[Cnt].pb(x);
siz[Cnt] += siz[x];
if(x == v) break;
}
Val[Cnt]++;
siz[u] += siz[Cnt];
}
else low[u] = min(low[v],low[u]);
}
}
}
void dfs(int u) {
if(Val[u] < 0) ans += (S - 1) * Val[u];
ans += 1LL * (S - siz[u]) * siz[u] * Val[u];
for(auto k : son[u]) {
ans += 1LL * siz[k] * (S - siz[k]) * Val[u];
}
for(auto k : son[u]) dfs(k);
}
void Init() {
read(N);read(M);
int u,v;
for(int i = 1 ; i <= M ; ++i) {
read(u);read(v);
add(u,v);add(v,u);
}
Cnt = N;
}
void Solve() {
for(int i = 1 ; i <= N ; ++i) {
if(!dfn[i]) {
Tarjan(i,0);
S = siz[i];
dfs(i);
}
}
printf("%lld\n",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
return 0;
}

【LOJ】#2587. 「APIO2018」铁人两项的更多相关文章

  1. 【刷题】LOJ 2587 「APIO2018」铁人两项

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

  2. LOJ #2587「APIO2018」铁人两项

    是不是$ vector$存图非常慢啊...... 题意:求数对$(x,y,z)$的数量使得存在一条$x$到$z$的路径上经过$y$,要求$x,y,z$两两不同  LOJ #2587 $ Solutio ...

  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. loj2587 「APIO2018」铁人两项

    圆方树orz,参见猫的课件(apio和wc的)以及这里那里 #include <iostream> #include <cstdio> using namespace std; ...

  6. 【APIO2018】铁人两项

    [APIO2018]铁人两项 题目描述 大意就是给定一张无向图,询问三元组\((s,c,f)\)中满足\(s\neq c\neq f\)且存在\((s\to c\to f)\)的简单路径(每个点最多经 ...

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

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

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

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

  9. LOJ #2585. 「APIO2018」新家

    #2585. 「APIO2018」新家 https://loj.ac/problem/2585 分析: 线段树+二分. 首先看怎样数颜色,正常的时候,离线扫一遍右端点,每次只记录最右边的点,然后查询左 ...

随机推荐

  1. python 套接字之select poll epoll

    python下的select模块使用 以及epoll与select.poll的区别 先说epoll与select.poll的区别(总结) select, poll, epoll 都是I/O多路复用的具 ...

  2. jdk1.8.0_45源码解读——ArrayList的实现

    jdk1.8.0_45源码解读——ArrayList的实现 一.ArrayList概述 ArrayList是List接口的可变数组的实现.实现了所有可选列表操作,并允许包括 null 在内的所有元素. ...

  3. R6—单变量正态性检验

    方法不唯一 单变量正态检验主要的话包括以下这些 shapiro.test();#Shapiro-Wilk检验 library("nortest"); lillie.test() # ...

  4. 20155232 2016-2017-3 《Java程序设计》第7周学习总结

    20155232 2016-2017-3 <Java程序设计>第7周学习总结 教材学习内容总结 第十三章 1.Greenwich MeanTime,格林威治时间,简称GMT时间,由观察太阳 ...

  5. 【leetcode 简单】 第五十九题 同构字符串

    给定两个字符串 s 和 t,判断它们是否是同构的. 如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的. 所有出现的字符都必须用另一个字符替换,同时保留字符的顺序.两个字符不能映射到同一 ...

  6. HDU 1427 速算24点 (深搜)

    题目链接 Problem Description 速算24点相信绝大多数人都玩过.就是随机给你四张牌,包括A(1),2,3,4,5,6,7,8,9,10,J(11),Q(12),K(13).要求只用' ...

  7. java_环境安装(window10)

    参考地址 下载JDK 下载地址:https://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html 本地环境变 ...

  8. [转]计算机视觉之跟踪算法——相关滤波器Correlation Filter

    https://blog.csdn.net/victoriaw/article/details/62416759 ASEF相关滤波器: Average of Synthetic Exact Filte ...

  9. [转]程序进行性能分析工具gprof使用入门

    性能分析工具 软件的性能是软件质量的重要考察点,不论是在线服务程序还是离线程序,甚至是终端应用,性能都是用户体验的关键.这里说的性能重大的范畴来讲包括了性能和稳定性两个方面,我们在做软件测试的时候也是 ...

  10. 2016.6.19——C++杂记

    C++杂记 补充的小知识点: 1.while(n--)和while(--n)区别: while(n--)即使不满足也执行一次循环后跳出. while(--n)不满足直接跳出循环,不执行语句. 用cou ...