【APIO2018】铁人两项

题目描述

大意就是给定一张无向图,询问三元组\((s,c,f)\)中满足\(s\neq c\neq f\)且存在\((s\to c\to f)\)的简单路径(每个点最多经过一次)的数量。

\(1\leq n,\leq 10^5,1\leq m\leq 2*10^5\)

我们考虑枚举\(s,f\)然后计算中间\(c\)的数量。我们发现对于一张图上统计两点之间路径上的点数量很好做。于是我们考虑建圆方树。

我们将圆点的权值定为\(-1\),将方点的权值定为与其直接相连的圆点的数量。\(u\)到\(v\)路径上可能经过的点的数量就是圆方树上\(u\to v\)路径上除了\(u,v\)的点权之和\(-2\)。

于是我们用树形\(\text{DP}\),计算每个点对答案的贡献。

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 200005 using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} int n,m;
int tot;
struct graph {
int to[N<<2],nxt[N<<2];
int h[N],cnt;
void add(int i,int j) {
to[++cnt]=j;
nxt[cnt]=h[i];
h[i]=cnt;
}
}s,g; int dfn[N],low[N],id;
int st[N];
int val[N]; void work(int v,int to) {
tot++;
g.add(v,tot);
val[tot]=1;
while(1) {
int j=st[st[0]--];
val[tot]++;
g.add(tot,j);
if(j==to) return ;
}
} ll tot_size;
void tarjan(int v,int fr) {
tot_size++;
dfn[v]=low[v]=++id;
st[++st[0]]=v;
for(int i=s.h[v];i;i=s.nxt[i]) {
int to=s.to[i];
if(to==fr) continue ;
if(!dfn[to]) {
tarjan(to,v);
low[v]=min(low[v],low[to]);
if(low[to]>=dfn[v]) {
work(v,to);
}
} else low[v]=min(low[v],dfn[to]);
}
} ll ans;
int size[N];
void dfs(int v) {
int tim=0;
for(int i=g.h[v];i;i=g.nxt[i]) {
int to=g.to[i];
dfs(to);
ans+=1ll*val[v]*size[v]*size[to];
tim+=size[v]*size[to];
size[v]+=size[to];
}
if(v<=n) size[v]++;
if(v<=n) {
tim+=(size[v]-1)*(tot_size-size[v]);
ans+=1ll*val[v]*(size[v]-1)*(tot_size-size[v]);
} else {
tim+=size[v]*(tot_size-size[v]);
ans+=1ll*val[v]*size[v]*(tot_size-size[v]);
}
} int main() {
n=Get(),m=Get();
tot=n;
int a,b;
for(int i=1;i<=m;i++) {
a=Get(),b=Get();
s.add(a,b),s.add(b,a);
}
for(int i=1;i<=n;i++) val[i]=-1;
for(int i=1;i<=n;i++) {
if(dfn[i]) continue ;
tot_size=0;
tarjan(i,0);
dfs(i);
ans-=1ll*tot_size*(tot_size-1);
}
cout<<ans*2;
return 0;
}

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

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

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

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

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

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

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

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

    过了14个月再重新看这题,发现圆方树从来就没有写过.然后写了这题发现自己APIO2018打铁的原因竟然是没开long long,将树的部分的O(n)写挂了(爆int),毕竟去年APIO时我啥都不会,连 ...

  5. 2019.03.29 bzoj5463: [APIO2018] 铁人两项(圆方树+树形dp)

    传送门 题意简述:给你一张无向图,问你满足存在从a−>b−>ca->b->ca−>b−>c且不经过重复节点的路径的有序点对(a,b,c)(a,b,c)(a,b,c) ...

  6. LOJ.2587.[APIO2018]铁人两项Duathlon(圆方树)

    题目链接 LOJ 洛谷P4630 先对这张图建圆方树. 对于S->T这条(些)路径,其对答案的贡献为可能经过的所有点数,那么我们把方点权值设为联通分量的大小,可以直接去求树上路径权值和. 因为两 ...

  7. [BZOJ5463][APIO2018]铁人两项:Tarjan+圆方树

    分析 根据题目中的要求,从\(s\)出发前往\(f\)一定可以,并且只可能经过这两个结点所在的点双连通分量和它们之间的点双连通分量,因此切换点\(c\)只能从这些点中选取. 建出圆方树后,因为圆方树上 ...

  8. 洛谷P4630 [APIO2018]铁人两项 [广义圆方树]

    传送门 又学会了一个新东西好开心呢~ 思路 显然,假如枚举了起始点\(x\)和终止点\(y\),中转点就必须在它们之间的简单路径上. 不知为何想到了圆方树,可以发现,如果把方点的权值记为双联通分量的大 ...

  9. [BZOJ5463] [APIO2018] 铁人两项

    题目链接 LOJ. BZOJ. Solution 先建圆方树. 我们考虑暴力,枚举一个点对,我们枚举的点都是圆点,然后统计中间那个点可以取的位置的数量,加起来就是答案. 那么怎么统计呢,我们对于每个点 ...

  10. LOJ2587:[APIO2018]铁人两项——题解

    https://loj.ac/problem/2587#submit_code (题面来自LOJ) 考试时候发觉树很可做,并且写了一个dp骗到了树的分. 苦于不会圆方树……现在回来发现这题还是很可做的 ...

随机推荐

  1. 从零开始学安全(八)●Ubuntu 16 LAMP环境搭建

    1.Apache2 web 服务器的安装 : 可以先更新一下服务器 sudo apt-get update # 获取最新资源包sudo apt-get upgrade # 本机软件全部更新sudo a ...

  2. [android] activity横竖屏切换的生命周期

    模拟器横竖屏切换,ctrl+f11 界面activity会销毁,重新打开创建 第一种做法: 定死就是横屏 在清单文件,<activity/>节点部分,添加属性,设置屏幕朝向 android ...

  3. Springboot@Configuration和@Bean详解

    Springboot@Configuration和@Bean详解 一.@Configuration @Target({ElementType.TYPE}) @Retention(RetentionPo ...

  4. springboot整合netty(二)

    目录 前言 正文 代码 1. 新建一个springboot项目,在pom文件中添加netty依赖: 2.新建netty服务 3.netty调用所需的服务类 4 springboot启动类 5.测试 我 ...

  5. Android view显示在软键盘上方

    给EditText外加一个ScrollView,将高度设置统一,并给ScrollView设置属性 android:fillViewport="true".  注:ScrollVie ...

  6. jquery对象和DOM对象的相互转换详解

    jquery对象和DOM对象的相互转换 在讨论jquery对象和DOM对象的相互转换之前,先约定好定义变量的风格如果获取的是jquery对象,那么在变量前面加上$,例如 var $varible = ...

  7. angular 过滤器(日期转换,时间转换,数据转换等)

    (function() { 'use strict'; /** * myApp Module * * Description */ angular.module('myApp') .filter('i ...

  8. Android Studio NDK JNI动态注册本地方法

    概述 可能大家觉得javah生成的函数名又臭又长,不太好看.这里可以提供另外一种方法来动态注册c++函数,让其根Java中的native方法关联起来. 实现 这里通过JNIEnv的Resisterna ...

  9. Android 内存管理中的 Shallow heap Retained heap

    所有包含Heap Profling功能的工具(MAT,Yourkit,JProfiler,TPTP等)都会使用到两个名词,一个是Shallow heap Size,另一个是 Retained heap ...

  10. Visual Studio语言设置

    按照的是中文的visual studio,用起来很不方便,因为程序员的都是英文版,平时交流时也是英文的名字 转换语言时发现只有中文和跟随windows系统的设置 官方给的文档看的不是很清楚 查阅资料后 ...