题目链接

题目要求我们求出任意两点间最短路径之和,由于图比较特殊,除树边外只有祖先到其子树内的边,我们首先考虑最短路径有没有什么特殊性质。

注意到两点之间的最短路分为一下三种:

  1. 节点到其祖先的最短路:直接沿着树边向上走即可,否则一定会走多余的边,不是最优。

  2. 节点到其子树的最短路:此时最短路一定形如沿着树边走若干条边,再走一条非树边,走若干条树边如此交替进行,当然此处也可以连续走非树边。

  3. 两个节点没有祖先孩子关系的最短路:如果此时要从 \(u\) 点走到 \(v\) 点,由于图中没有横叉边,\(u\) 点必须要走到 \(\operatorname{lca}(u,v)\),否则一定无法通过非树边到 \(v\) 点,之后转为为从 \(\operatorname{lca}(u,v)\) 到 \(v\) 的第二类最短路。

这三条最短路都会经过 \(\operatorname{lca}(u,v)\),由于其唯一性,考虑枚举最近公共祖先统计答案,第二类是方便统计的,而此时第一类也已经被处理了,我们把第三类分为两部分:从 \(u\) 到 \(\operatorname{lca}(u,v)\) 和 从 \(\operatorname{lca}(u,v)\) 到 \(v\)。

第一段通过预处理即可解决,对于每个枚举到的 \(\operatorname{lca}\),由于树高是 \(\log\) 的,第二段路径所牵扯到的节点数也不会超过 \(N\log N\) 个,因此可以直接建反图暴力跑最短路统计,之后模仿点分治计算一遍即可。

代码中我对于每个 \(\operatorname{lca}\) 的子节点正序倒序分别枚举了一次,枚举到每颗子树时累加前面的子树走前半段,这颗子树走后半段的答案,即可保证不重不漏。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define ll long long
#define N 700005
using namespace std;
const ll mod=998244353;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll tot,dsum[N],dfn[N],ri[N],val[N],dis[N],vis[N],dep[N];
ll bel[N],siz[N],ans,ttp[N],sta[N],p,ct[N];
struct graph{
ll e,head[N],to[N],nex[N],edg[N];
void add(ll u,ll v,ll w){
to[++e]=v;nex[e]=head[u];head[u]=e;edg[e]=w;
}
void clear(){
for(ll i=1;i<=e;i++)head[i]=nex[i]=edg[i]=to[i]=0;
e=0;
}
}T,G;
struct edg{
ll u,v,w;
};
struct Node{
ll v,val;
bool operator <(const Node &x)const{
return val>x.val;
}
};
void adj(ll &x){
x=(((x%mod)+mod)%mod);
}
priority_queue<Node> q;
vector<edg> E[N];
void dfs(ll x){
dfn[x]=++tot;bel[tot]=x;siz[x]=1;
for(ll i=T.head[x];i;i=T.nex[i]){
ll v=T.to[i],w=T.edg[i];dep[v]=dep[x]+w;adj(dep[v]);dfs(v);
dsum[x]+=w*siz[v]+dsum[v];dsum[x]%=mod;
siz[x]+=siz[v];
}
ri[x]=tot;
}
void dij(ll s){
q.push((Node){s,0});dis[s]=0;
while(q.size()){
ll x=q.top().v;q.pop();if(vis[x]) continue;
vis[x]++;
for(ll i=G.head[x];i;i=G.nex[i]){
ll v=G.to[i],w=G.edg[i];
if(dis[v]>dis[x]+w){
dis[v]=dis[x]+w;
q.push((Node){v,dis[v]});
}
}
}
}
void dfs2(ll x){
G.clear();
for(ll i=dfn[x];i<=ri[x];i++){
dis[i]=inf;vis[i]=0;ans+=dep[bel[i]]-dep[x];adj(ans);
for(ll j=0;j<E[bel[i]].size();j++){
G.add(dfn[E[bel[i]][j].u],dfn[E[bel[i]][j].v],E[bel[i]][j].w);
}
G.add(dfn[bel[i]],dfn[bel[i]/2],val[bel[i]]);
}
ll tmp=x,tmp2=x/2,sumdis=0,sumsiz=1,cnt=0,tp=0;
while(tmp2){
G.add(dfn[tmp],dfn[tmp2],val[tmp]);
vis[dfn[tmp]]=0;dis[dfn[tmp]]=inf;tmp=tmp2;tmp2/=2;
}
vis[1]=0;dis[1]=inf;dij(dfn[x]);tmp=x;p=0;
for(ll i=T.head[x];i;i=T.nex[i]){
sta[++p]=i;ll v=T.to[i];tp=0;cnt=0;
for(ll j=dfn[v];j<=ri[v];j++){
if(dis[j]!=inf){
tp+=dis[j];adj(tp);cnt++;
}
}
ttp[v]=tp;ct[v]=cnt;
ans+=((sumsiz*tp)%mod)+((cnt*sumdis)%mod);adj(ans);
sumsiz+=siz[v];adj(sumsiz);
sumdis+=dsum[v]+((T.edg[i]*siz[v])%mod);adj(sumdis);
}
sumsiz=sumdis=0;
for(ll i=p;i>=1;i--){
ll j=sta[i],v=T.to[j];tp=ttp[v];cnt=ct[v];
ans+=((sumsiz*tp)%mod)+((cnt*sumdis)%mod);adj(ans);
sumsiz+=siz[v];adj(sumsiz);
sumdis+=dsum[v]+((T.edg[j]*siz[v])%mod);adj(sumdis);
}
for(ll i=dfn[x];i<=ri[x];i++)G.head[i]=dis[i]=0;
while(tmp){G.head[dfn[tmp]]=0;dis[dfn[tmp]]=0;tmp/=2;}
for(ll i=T.head[x];i;i=T.nex[i])dfs2(T.to[i]);
}
ll read(){
ll x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int main(){
ll n,m,u,v,w;n=read();m=read();n=(1<<n)-1;
for(ll i=2;i<=n;i++){cin>>w;T.add((i/2),i,w);val[i]=w;}
for(ll i=1;i<=m;i++){
u=read();v=read();w=read();
E[v].push_back((edg){u,v,w});
}
dfs(1);dfs2(1);
cout<<ans;
}

P9481 [NOI2023] 贸易 题解的更多相关文章

  1. 「NOIP2009」最优贸易 题解

    「NOIP2009」最优贸易 题解 题目TP门 题目描述 \(C\)国有\(n\)个大城市和\(m\)条道路,每条道路连接这\(n\)个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 ...

  2. 51NOD 1773:A国的贸易——题解

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1773 参考1:FWT讲解 https://www.cnblogs.com ...

  3. NOIP 2009 最优贸易 题解

    一道最短路的题,找一个买入和卖出相差最高的点即可,我们先以1为起点跑spfa,d1[x]不再表示距离而表示能够经过权值最小的节点的权值即 if(d1[y]>min(d1[x],price[y]) ...

  4. 洛谷 P1073 最优贸易 题解

    题面 大家都是两遍SPFA吗?我这里就一遍dp啊: 首先判断对于一个点u,是否可以从一号点走到这里,并且可以从u走到n号点: 对于这样的点我们打上标记: 那么抛出水晶球的点一定是从打上标记的点中选出一 ...

  5. bzoj1205: [HNOI2005]星际贸易

    题目链接 bzoj1205: [HNOI2005]星际贸易 题解 辣鸡题面,毁我青春 辣鸡题面,毁我青 辣鸡题面,毁我 辣鸡题面,毁 第一问,背包dp 第二问 问题转化为在一个序列上经过好多点走到终点 ...

  6. 【题解】洛谷P1073 [NOIP2009TG] 最优贸易(SPFA+分层图)

    次元传送门:洛谷P1073 思路 一开始看题目嗅出了强连通分量的气息 但是嫌长没打 听机房做过的dalao说可以用分层图 从来没用过 就参考题解了解一下 因为每个城市可以走好几次 所以说我们可以在图上 ...

  7. 【luogu P1073 最优贸易】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1073 对于状态量相互影响的题目,分层图是个不错的想法. 考虑在题目中分为: 不交易: 直接从1到n出去,为0 ...

  8. 题解【luogu1073 最优贸易】

    Solution 考虑原图是 DAG 时怎么做. 拓扑排序 + dp ,令 dp[i] 表示 \(1\) 到 \(i\) 的路径上最小的卖出价格.转移方程就是对每一个可以到达这个点的 dp 取个 mi ...

  9. noip2009提高组题解

    NOIP2009题解 T1:潜伏者 题目大意:给出一段密文和破译后的明文,一个字母对应一个密文字母,要求破译一段密文,如果有矛盾或有未出现密文无法破译输出failed,否则输出明文. 思路:纯模拟题 ...

  10. 历年NOIP选题题解汇总

    联赛前上vijos板刷往年联赛题,使用在线编辑编写代码,祝我rp++. 废话不多说,挑比较有意思的记一下. 题目是按照年份排序的,最早只到了03年. 有些题目因为 我还没写/很早之前写的忘了 所以就没 ...

随机推荐

  1. AutoCAD 2024下载及安装教程

    安装教程 演示操作系统:Windows 11 *安装前请关闭所有杀毒软件,避免报错 1.解压[CAD2024.zip] 2.打开解压的[CAD2024]文件夹,打开[Setup]文件夹,运行[Setu ...

  2. 基于AIidlux平台的自动驾驶环境感知与智能预警

    自动驾驶汽车又称为无人驾驶车,是一种需要驾驶员辅助或者完全不需操控的车辆. 自动驾驶分级: 自动驾驶系统的组成部分: 环境感知系统: 自动驾驶系统架构: 自动驾驶数据集: Aidlux的作用: YOL ...

  3. Tcpdump 使用指南

    论网络数据包的分析,我首选wireshark,因为图形化界面直观明了.但如果遇到没有图形化显示的Linux环境,那么此时会使用tcpdump该是一件多么美好的事情. 网上关于tcpdump的介绍很多, ...

  4. [linux]常见内核TCP参数描述与配置

    前言 所有的TCP/IP参数都位于/proc/sys/net目录下(请注意,对/proc/sys/net目录下内容的修改都是临时的,任何修改在系统重启后都会丢失),如果需要固化设置,则需要修改/etc ...

  5. php批量同步数据

    php批量同步流程 首先分页获取数据 创建临时表 批量添加数据 备份原表 删除原表 修改临时表表名改为原表 代码 1 <?php 2 3 class Stock{ 4 5 private $da ...

  6. Godot无法响应鼠标点击等输入事件时,检查这些内容

    注:本文以Godot 4.0 为基准,可能其他版本也能参考. 这是我用C#写项目时发现的,可能和gdscript使用者遇到的问题有一定区别. 如果你用Godot制作的游戏无法响应鼠标点击等输入事件,请 ...

  7. servlet系列:简介和基本使用以及工作流程

    目录 一.简介 二.Servlet实现 三.基本使用 1.引入pom依赖 2.实现Servlet规范,重写service方法 3.配置web.xml 4.配置Tomcat 6.运行 四.Servlet ...

  8. 《SQL与数据库基础》21. 分库分表(一)

    目录 分库分表(一) 拆分策略 垂直拆分 垂直分库 垂直分表 水平拆分 水平分库 水平分表 技术实现 MyCat概述 概念介绍 环境准备 目录介绍 MyCat入门 配置 分片配置(schema.xml ...

  9. ctypes使用浅谈

    什么是ctypes: ctypes 是 Python 的一个标准库,用于与 C 语言进行交互.它提供了一组工具和函数,可以方便地调用动态链接库(DLL)或共享对象(SO)中的 C 函数,并处理 C 数 ...

  10. vue + canvas 实现九宮格手势解锁器

    前言 专栏分享:vue2源码专栏,vue router源码专栏,玩具项目专栏,硬核推荐 欢迎各位 ITer 关注点赞收藏 此篇文章用于记录柏成从零开发一个canvas九宮格手势解锁器的历程,最终效果如 ...