[BZOJ5463][APIO2018]铁人两项:Tarjan+圆方树
分析
根据题目中的要求,从\(s\)出发前往\(f\)一定可以,并且只可能经过这两个结点所在的点双连通分量和它们之间的点双连通分量,因此切换点\(c\)只能从这些点中选取。
建出圆方树后,因为圆方树上一条路径的两个端点(圆点)不能作为切换点,并且路径上其他的圆点都被两个路径上的点双连通分量所包含,可以发现,如果把方点的权值设为这个点双连通分量的\(siz\),圆点的权值设为\(-1\),那么圆方树上所有两个端点都是圆点的路径的权值和就是答案。这个问题可以通过考虑每个结点在多少条路径上来解决。
时间复杂度为\(O(n)\)。
代码
#include <bits/stdc++.h>
#define rin(i,a,b) for(register int i=(a);i<=(b);++i)
#define irin(i,a,b) for(register int i=(a);i>=(b);--i)
#define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
typedef __int128 LL;
using std::cin;
using std::cout;
using std::endl;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void write(LL x){
if(x/10) write(x/10);
putchar(x%10+'0');
}
void writeln(LL x){
write(x);
putchar('\n');
}
const int MAXN=1e6+5;
const int MAXM=2e6+5;
int n,m,ecnt,head[MAXN<<1];
int dfn[MAXN],low[MAXN],tot;
int sta[MAXN],top;
int cnt;
int totsiz,siz[MAXN<<1];
LL ans;
bool vis[MAXN<<1];
std::vector<int> vdcc[MAXN];
struct Edge{
int to,nxt;
}e[MAXM<<2];
inline void add_edge(int bg,int ed){
++ecnt;
e[ecnt].to=ed;
e[ecnt].nxt=head[bg];
head[bg]=ecnt;
}
void tarjan(int x){
dfn[x]=low[x]=++tot;
sta[++top]=x;
trav(i,x){
int ver=e[i].to;
if(!dfn[ver]){
tarjan(ver);
low[x]=std::min(low[x],low[ver]);
if(low[ver]>=dfn[x]){
++cnt;int las=0;
vdcc[cnt].push_back(x);
while(las!=ver){
las=sta[top];
vdcc[cnt].push_back(sta[top]);
--top;
}
}
}
else low[x]=std::min(low[x],dfn[ver]);
}
}
int getsiz(int x,int pre){
int ret=0;
trav(i,x){
int ver=e[i].to;
if(ver==pre) continue;
ret+=getsiz(ver,x);
}
if(x<=n) ++ret;
return ret;
}
void dfs(int x,int pre){
vis[x]=true;
trav(i,x){
int ver=e[i].to;
if(ver==pre) continue;
dfs(ver,x);
if(x<=n) ans-=1ll*siz[ver]*siz[x]*2;
else ans+=1ll*siz[ver]*siz[x]*(LL)vdcc[x-n].size()*2;
siz[x]+=siz[ver];
}
if(x<=n) ans-=1ll*(siz[x]+1)*(totsiz-siz[x])*2-2,++siz[x];
else ans+=1ll*siz[x]*(totsiz-siz[x])*(LL)vdcc[x-n].size()*2;
}
int main(){
n=read(),m=read();
rin(i,1,m){
int u=read(),v=read();
add_edge(u,v);
add_edge(v,u);
}
rin(i,1,n){
if(dfn[i]) continue;
if(!head[i]){
vdcc[++cnt].push_back(i);
continue;
}
top=0;tarjan(i);
}
ecnt=0;memset(head,0,sizeof head);
rin(i,1,cnt){
rin(j,0,(int)vdcc[i].size()-1){
add_edge(n+i,vdcc[i][j]);
add_edge(vdcc[i][j],n+i);
}
}
rin(i,1,n){
if(vis[i]) continue;
totsiz=getsiz(i,0);
dfs(i,0);
}
writeln(ans);
return 0;
}
[BZOJ5463][APIO2018]铁人两项:Tarjan+圆方树的更多相关文章
- 2019.03.29 bzoj5463: [APIO2018] 铁人两项(圆方树+树形dp)
传送门 题意简述:给你一张无向图,问你满足存在从a−>b−>ca->b->ca−>b−>c且不经过重复节点的路径的有序点对(a,b,c)(a,b,c)(a,b,c) ...
- [APIO2018]铁人两项(圆方树)
过了14个月再重新看这题,发现圆方树从来就没有写过.然后写了这题发现自己APIO2018打铁的原因竟然是没开long long,将树的部分的O(n)写挂了(爆int),毕竟去年APIO时我啥都不会,连 ...
- LOJ.2587.[APIO2018]铁人两项Duathlon(圆方树)
题目链接 LOJ 洛谷P4630 先对这张图建圆方树. 对于S->T这条(些)路径,其对答案的贡献为可能经过的所有点数,那么我们把方点权值设为联通分量的大小,可以直接去求树上路径权值和. 因为两 ...
- 洛谷P4630 [APIO2018]铁人两项 [广义圆方树]
传送门 又学会了一个新东西好开心呢~ 思路 显然,假如枚举了起始点\(x\)和终止点\(y\),中转点就必须在它们之间的简单路径上. 不知为何想到了圆方树,可以发现,如果把方点的权值记为双联通分量的大 ...
- 【APIO2018】铁人两项(圆方树,动态规划)
[APIO2018]铁人两项(圆方树,动态规划) 题面 UOJ 洛谷 BZOJ 题解 嘤嘤嘤,APIO的时候把一个组合数写成阶乘了,然后这题的70多分没拿到 首先一棵树是很容易做的,随意指定起点终点就 ...
- 洛谷P4630 [APIO2018] Duathlon 铁人两项 (圆方树)
圆方树大致理解:将每个点双看做一个新建的点(方点),该点双内的所有点(圆点)都向新建的点连边,最后形成一棵树,可以给点赋予点权,用以解决相关路径问题. 在本题中,方点点权赋值为该点双的大小,因为两个点 ...
- 洛谷P4630 [APIO2018] Duathlon 铁人两项 【圆方树】
题目链接 洛谷P4630 题解 看了一下部分分,觉得树的部分很可做,就相当于求一个点对路径长之和的东西,考虑一下能不能转化到一般图来? 一般图要转为树,就使用圆方树呗 思考一下发现,两点之间经过的点双 ...
- 【APIO 2018】铁人两项(圆方树)
题目链接 题意大概是,求有多少三元组$(s,c,f)(s \neq c, c \neq f, s \neq f)$,满足从$s$到$f$有一条简单路径经过$c$. 得到结论: 点双中任意互不相同的三个 ...
- 洛谷4630APIO2018铁人两项(圆方树+dp)
QWQ神仙题啊(据说是今年第一次出现圆方树的地方) 首先根据题目,我们就是求对于每一个路径\((s,t)\)他的贡献就是两个点之间的点数,但是图上问题我并没有办法很好的解决... 这时候考虑圆方树,我 ...
- P4630-[APIO2018]Duathlon铁人两项【圆方树】
正题 题目链接:https://www.luogu.com.cn/problem/P4630 题目大意 \(n\)个点\(m\)条边的一张无向图,求有多少对三元组\((s,c,f)\)满足\(s\ne ...
随机推荐
- Java初始和环境搭建
前世今生 Java语言是什么? 一种计算机编程语言.名字取自咖啡. Java语言发展简史 Java语言之父:James Gosling SUN(Stanford University Network ...
- 如何使用 re模块的, spilt.
例: 这是一组 网卡的信息. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN link/loopb ...
- [洛谷P4183][USACO18JAN]Cow at Large P
题目链接 Bzoj崩了之后在洛谷偶然找到的点分好题! 在暴力的角度来说,如果我们$O(n)$枚举根节点,有没有办法在$O(n)$的时间内找到答案呢? 此时如果用树形$dp$的想法,发现是可做的,因为可 ...
- [BZOJ2964]Boss单挑战
题目描述 某\(RPG\)游戏中,最后一战是主角单挑\(Boss\),将其简化后如下: 主角的气血值上限为\(HP\),魔法值上限为\(MP\),愤怒值上限为\(SP\):\(Boss\)仅有气血值, ...
- Ubuntu下TP5隐藏入口文件
部分内容是复制其他网友的博文,由于过了一段时间,找不到原文地址,再次表示感谢.以下是自己整理的,目的只是以后方便查阅 1.ubuntu或linux下找不到apache服务器配置文件httpd.conf ...
- qt嵌入式html和本地c++通信方式
前沿:我们在做qt项目的时候,通常会把某个html网页直接显示到应用程序中.比如绘图.直接把html形式的图标嵌入到应用程序中 但是我们需要把数据从后台c++端传到html端,实现显示.qt实现了相关 ...
- openlayers之地图测距侧面
项目背景vue-cli3.0 public下html需要引入文件 <link rel="stylesheet" href="<%= BASE_URL %> ...
- 下载 Eclipse 免安装版~
进入https://www.eclipse.org/downloads/
- [转载]排序:长度为n的数组乱序存放着0至n-1. 现在只能进行0与其他数的swap
长度为n的数组乱序存放着0至n-1. 现在只能进行0与其他数的swap 请设计并实现排序. google笔试小题.题目来源:http://wenku.baidu.com/view/5aa818dda5 ...
- Spring基础20——AOP基础
1.什么是AOP AOP(Aspect-Oriented Programming)即面向切面编程,是一种新的方法论,是对那个传统OOP面向对象编程的补充.AOP的主要编程对象是切面(aspect),而 ...