【APIO2018】铁人两项

【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;
}

原文地址:https://www.cnblogs.com/hchhch233/p/10574714.html

时间: 2024-11-10 16:13:07

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

[圆方树] Luogu P4630 Duathlon 铁人两项

题目描述 比特镇的路网由 mm 条双向道路连接的 nn 个交叉路口组成. 最近,比特镇获得了一场铁人两项锦标赛的主办权.这场比赛共有两段赛程:选手先完成一段长跑赛程,然后骑自行车完成第二段赛程. 比赛的路线要按照如下方法规划: 先选择三个两两互不相同的路口 s, cs,c和 ff,分别作为比赛的起点.切换点(运动员在长跑到达这个点后,骑自行车前往终点).终点. 选择一条从 ss出发,经过 cc最终到达 ff的路径.考虑到安全因素,选择的路径经过同一个点至多一次. 在规划路径之前,镇长想请你帮忙计

luogu 4630 [APIO2018] Duathlon 铁人两项

题目大意: 无向图上找三个点 a b c使存在一条从a到b经过c的路径 求取这三个点的方案数 思路: 建立圆方树 这个圆方树保证没有两个圆点相连或两个方点相连 对于每个节点x 设该节点为路径的中间节点 则a c要么同在一个子树内 要么一个在子树内另一个在子树外 最后对答案<<1 对于每个方点设val[x] 为该点所连圆点的个数 每个方点按照两种情况算出答案之后 用圆点减去算重的部分 1 #include<iostream> 2 #include<cstdio> 3 #i

铁人两项

题目描述: 给定无向图G,包含n个点m条边(不保证连通),求有序三元组(s,c,f)个数要求满足 s, c, f 都是图中的点,且存在一条从s到c的路径和一条从c到f的路径,使得两条路径没有公共点(除c外). 在这里我们引进圆方树的概念. 但首先我们要了解一下点双和边双. 在无向图中: 点双:极大的连通子图,使得删掉这个子图中的任何一个点,这个子图仍然连通. 也就是说,在这个极大的连通子图中没有割点. 也就是说,在这个极大的连通子图中两个不同节点可以通过两条没有公共点的路径互相到达,但是排除起点

【BZOJ】【2765】【JLOI2010】铁人双项比赛

计算几何/半平面交 本来我是想去写POJ 1755的,然后想起了这道跟它很像的题,但应该是弱化版,所以就先写了这个…… 我们可以发现每个人的总用时,与k是呈一次函数关系的:$time_i=\frac{k}{Vrun_i}+\frac{S-k}{Vride_i}$ 然而我们要找的是某个k,使得$min(time_n-time_i)$最大 那么就是一个线性规划问题了……这个也可以用半平面交来做……(蒟蒻并不会单纯形) 下面的部分为了偷懒简洁我就用$a_i$和$b_i$来代替两种速度…… 我一开始想的

为什么Fibonacci数列相邻两项之比会趋于0.618

转帖: http://www.matrix67.com/blog/archives/5221 你或许熟知一个非常经典的结论: Fibonacci 数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, … (头两项都是 1 ,此后每一项都是前两项之和)的相邻两项之比将会越来越接近黄金比例 0.618 ,不信请看: 1 / 1 = 1.0000000... 1 / 2 = 0.50000000... 2 / 3 = 0.66666667... 3 / 5 = 0.60000000

数据包分析之信息安全铁人三项

电子取证是指利用计算机软硬件技术,以符合法律规范的方式对计算机入侵.破坏.欺诈.攻击等犯罪行为进行证据获取.保存.分析和出示的过程.从技术方面看,计算机犯罪取证是一个对受侵计算机系统进行扫描和破解,对入侵事件进行重建的过程.具体而言,是指把计算机看作犯罪现场,运用先进的辨析技术,对计算机犯罪行为进行解剖,搜寻罪犯及其犯罪证据. 随着计算机犯罪个案数字不断上升和犯罪手段的数字化,搜集电子证据的工作成为提供重要线索及破案的关键.恢复已被破坏的计算机数据及提供相关的电子资料证据就是电子取证. 本文针对

求斐波那契数列的相邻两项的比值,精确到小数后三位。

未完成,只能假设知道是9和10代入. 代码如下: package zuoye; import java.math.BigDecimal; /* * 求斐波那契数列的相邻两项的比值,精确到小数后三位. * p1,p2,p3......pi,pj,...求pi/pj * 1 1 2 3 5 8 13 * 5/8,8/13,...收敛 */ public class Test { static double feibo(int x){ if(x==1||x==2) return 1; return f

两项基于网络的“黑客”技术

两项基于网络的“黑客”技术 软件开发和测试中网络环境迁移和数据分析 1   导读 关于智能路由器的这两项技术的介绍,想想还是搞个比较有噱头的标题才能吸引人进来细看的.本文确实是介绍的两个关于智能路由器的hack技术,但是却是将这两项技术用于软件开发过程中的正途中的.当然如果有悟性,也可以将此技术用于不违法的恶作剧玩一下也无妨. 本文提到的两个基于网络的hack技术: DNS劫持 数据抓包 基本本质上就是路由器设备的两个主要网络功能: 网关配置功能 网关数据中转功能 但是用于软件开发的正途,就变换

突破两项吉尼斯世界纪录浙江商帮全体高层应邀参观阿里巴巴

淘宝安全交易平台 www.xunjie36.com 淘宝店铺出售www.360feiyue.com 淘宝店铺交易www.360feiyue.com[关键词]淘宝安全交易平台 www.xunjie36.com 淘宝店铺出售www.360feiyue.com 淘宝店铺交易www.360feiyue.com淘宝小号信誉查询 此次阿里上市后的第一个"双十一",销售破百亿仅用38分钟:13个小时,成交额便已超过去年全天的销售总额362亿元:最终的成交额定格在571亿: 突破两项吉尼斯世界纪录,分