题目描述

mzry1992 在打完吊针出院之后,买了辆新摩托车,开始了在周边城市的黄金运送生意。在mzry1992 生活的地方,城市之间是用双向高速公路连接的。另外,每条高速公路有一个载重上限,即在不考虑驾驶员和摩托车重量的情况下,如果所载货物的量超过某个值,则不能驶上该条高速公路。

今年,mzry1992 一共收到了来自n 个不同城市的n 份定订单,每个订单要求卖出上限为一定量的黄金,或是要求买入上限为一定量的黄金。由于订单并不是同时发来的,为了维护生意上的名声,mzry1992 不得不按照订单发来的顺序与客户进行交易。他与第i 个客户进行交易的具体步骤是:

1.前往第i 个客户所在城市。当然,中途是完全允许经过其他城市的。

2.与第i 个客户进行交易,在此过程中他希望有限制的让交易额尽量大。具体的限制有两个

(a) 他希望与最后一个客户完成交易后,手上没有剩余黄金。

(b) 由于黄金是很贵重的物品,不能出现因为买入过多黄金而造成在以后的运送过程中不得不丢弃黄金的情况。

一开始,mzry1992 位于第一个订单客户所在的城市。现在有一个好消息,有人提供了mzry1992 免费试用周边城市的列车系统的资格。具体来讲,如果mzry1992希望从A 城市到达B 城市,且A、B 城市均有列车站的话,他可以携带着黄金与摩托车从A 城市乘坐列车到B 城市,这里假定乘坐列车没有载重限制。

现在已知城市间的交通系统情况和订单情况,请帮助mzry1992 计算每个向mzry1992 购买黄金的客户的购买量。

思路

首先,经过的路径一定在最大生成树上。

其次,不需要考虑交易后剩余黄金的情况,因为可以根据客户的需求而调整买入多少。

这样,跑一遍最大生成树,再用树剖维护树上路径最小值,来看买入多少。

代码

/************************************************
*Author : lrj124
*Created Time : 2019.10.10.21:11
*Mail : 1584634848@qq.com
*Problem : luogu3280
************************************************/
#include <algorithm>
#include <cstring>
#include <cstdio>
#define int ll
using ll = long long;
using namespace std;
const ll inf = 10000000000000ll;
const int maxn = 100000 + 10;
int egcnt,n,m,q,cnt,per[maxn],dep[maxn],father[maxn],top[maxn],num[maxn],val[maxn],Map[maxn],siz[maxn],son[maxn],fir[maxn];
struct Edge { int to,nex; ll w; } eg[maxn];
ll minv[maxn<<2],w[maxn];
struct Road {
int u,v;
ll w;
inline bool operator < (Road cmp) {
return w > cmp.w;
}
} edge[maxn*3];
inline void addedge(int u,int v,ll w) {
eg[++egcnt] = {v,fir[u],w}; fir[u] = egcnt;
eg[++egcnt] = {u,fir[v],w}; fir[v] = egcnt;
}
inline void dfs1(int now,int fa) {
siz[now] = 1;
father[now] = fa;
dep[now] = dep[fa]+1;
for (int i = fir[now];~i;i = eg[i].nex)
if (eg[i].to ^ fa) {
dfs1(eg[i].to,now);
val[eg[i].to] = eg[i].w;
siz[now] += siz[eg[i].to];
if (siz[son[now]] < siz[eg[i].to]) son[now] = eg[i].to;
}
}
inline void dfs2(int now,int ntop) {
num[now] = ++cnt;
Map[cnt] = now;
top[now] = ntop;
if (son[now]) dfs2(son[now],ntop);
for (int i = fir[now];~i;i = eg[i].nex)
if (eg[i].to ^ father[now] && eg[i].to ^ son[now]) dfs2(eg[i].to,eg[i].to);
}
inline void pushup(int root) { minv[root] = min(minv[root<<1],minv[root<<1|1]); }
inline void build(int l,int r,int root) {
if (l == r) {
minv[root] = val[Map[l]];
return;
}
int mid = l+r>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
pushup(root);
}
inline ll query(int l,int r,int ql,int qr,int root) {
if (l > qr || r < ql) return inf;
if (ql <= l && r <= qr) return minv[root];
int mid = l+r>>1;
return min(query(l,mid,ql,qr,root<<1),query(mid+1,r,ql,qr,root<<1|1));
}
inline ll query_edge(int u,int v) {
ll ans = inf;
for (;top[u] ^ top[v];u = father[top[u]]) {
if (dep[top[u]] < dep[top[v]]) swap(u,v);
ans = min(ans,query(1,n,num[top[u]],num[u],1));
}
if (dep[u] > dep[v]) swap(u,v);
return min(ans,query(1,n,num[u]+1,num[v],1));
}
inline int find(int x) { return father[x] = father[x] == x ? x : find(father[x]); }
inline void kruskal() {
for (int i = 1;i <= n;i++) father[i] = i;
if (!q) q = 1;
int cnt = 0;
sort(edge+1,edge+m+q);
for (int i = 1,x,y;i <= m+q-1;i++) {
x = find(edge[i].u);
y = find(edge[i].v);
if (x ^ y) {
father[x] = y;
addedge(edge[i].u,edge[i].v,edge[i].w);
cnt++;
}
if (cnt == n-1) break;
}
memset(father,0,sizeof(father));
}
signed main() {
// freopen("luogu3280.in","r",stdin);
// freopen("luogu3280.out","w",stdout);
memset(fir,-1,sizeof(fir));
scanf("%lld%lld%lld",&n,&m,&q);
for (int i = 1;i <= n;i++) scanf("%lld",&per[i]);
for (int i = 1;i <= n;i++) scanf("%lld",&w[i]);
for (int i = 1;i <= m;i++) scanf("%lld%lld%lld",&edge[i].u,&edge[i].v,&edge[i].w);
for (int i = 1,x,y;i <= q;i++) { scanf("%lld",&x); if (i ^ 1) edge[m+i-1] = {x,y,inf}; y = x; }
kruskal();
dfs1(1,0);
dfs2(1,1);
build(1,n,1);
ll now = 0;
for (int i = 1;i < n;i++)
if (w[per[i]] > 0) now = min(now+w[per[i]],query_edge(per[i],per[i+1]));
else {
printf("%lld\n",min(-w[per[i]],now));
now = min(max(0ll,now+w[per[i]]),query_edge(per[i],per[i+1]));
}
if (w[per[n]] < 0) printf("%lld",min(-w[per[n]],now));
return 0;
}

【SCOI2013】摩托车交易 - 最大生成树+树链剖分的更多相关文章

  1. BZOJ3322[Scoi2013]摩托车交易——最大生成树+贪心+倍增

    题目描述 mzry1992 在打完吊针出院之后,买了辆新摩托车,开始了在周边城市的黄金运送生意.在mzry1992 生活的地方,城市之间是用双向高速公路连接的.另外,每条高速公路有一个载重上限,即在不 ...

  2. NOIP2013D1T3货车运输 (生成树+树链剖分)

    给出一个图,询问图上两点间路径上最小边权的最大值. 先跑一次最大生成树. 树剖维护路径最小边权. 树剖又双叒叕写挂了. #include<cstring> #include<cstd ...

  3. NOIP 2013 货车运输【Kruskal + 树链剖分 + 线段树 】【倍增】

    NOIP 2013 货车运输[树链剖分] 树链剖分 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在 ...

  4. [wikioi 1519]过路费(最小生成树+树链剖分)

    题目:http://www.wikioi.com/problem/1519/ 题意:给你一个连通的无向图,每条边都有权值,给你若干个询问(x,y),要输出从x到y的路径上边的最大值的最小值 分析:首先 ...

  5. Educational Codeforces Round 3 E. Minimum spanning tree for each edge (最小生成树+树链剖分)

    题目链接:http://codeforces.com/contest/609/problem/E 给你n个点,m条边. 问枚举每条边,问你加这条边的前提下组成生成树的权值最小的树的权值和是多少. 先求 ...

  6. BZOJ 1103: [POI2007]大都市meg( 树链剖分 )

    早上数学考挂了...欲哭无泪啊下午去写半个小时政治然后就又可以来刷题了.. 树链剖分 , 为什么跑得这么慢... ------------------------------------------- ...

  7. Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树+树链剖分+线段树

    E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...

  8. 1103. [POI2007]MEG-Megalopolis【树链剖分】

    Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了. 不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1.. ...

  9. 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树

    题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...

随机推荐

  1. vue-methods三种调用的形势

    var btn = { template:`<button>组件add</button>` } var any = new Vue({ el: '#app', data:{ a ...

  2. R 基础绘图体系-基础篇

    1.高水平绘图函数 生成数据 #模拟100位同学学号及三科成绩 num = seq(12340001,12340100) # 形成学号 x1 = round(runif(100,min = 80,ma ...

  3. API返回延迟,FPM重启后恢复之后又重现 问题解决方案

    背景 最近在提供后台API时,提供了一个简单逻辑的接口 部署在测试环境,自测没问题,提交测试 突然有一天,接口响应延迟严重,几乎每次都是3-4秒返回 这对于一个接口来说,肯定是有问题的 于是便有了以下 ...

  4. PHP easter_days() 函数

    ------------恢复内容开始------------ 实例 输出不同年份的复活节与 3 月 21 日之间的天数: <?phpecho "Easter Day is " ...

  5. 51nod 1584 加权约数和 约数和函数小trick 莫比乌斯反演

    LINK:加权约数和 我曾经一度认为莫比乌斯反演都是板子题. 做过这道题我认输了 不是什么东西都是板子. 一个trick 设\(s(x)\)为x的约数和函数. 有 \(s(i\cdot j)=\sum ...

  6. CF Contest 526 G. Spiders Evil Plan 长链剖分维护贪心

    LINK:Spiders Evil Plan 非常巧妙的题目. 选出k条边使得这k条边的路径覆盖x且覆盖的边的边权和最大. 类似于桥那道题还是选择2k个点 覆盖x那么以x为根做长链剖分即可. 不过这样 ...

  7. C#与网络相关的两个监听的事件

    今天遇到一个问题,当网络连接有问题的时候设计软件向用户发送通知,查了资料发现了两个相关的事件分享一下. 一.System.Net.NetworkInformation命名空间下的NetworkChan ...

  8. 《分享》Graphql入门与实践

    最近项目用到了graphql,学习了一些并在公司做了一个小分享,希望对你有帮助 一.介绍 Graphql是一种面向数据的API查询语言 Graphql给前端提供一种强力的查询工具,我们可以根据自己定义 ...

  9. map进程数量和reduce进程数量

    1-map task的并发数量是由切片的数量决定的,有多少个切片就有启动多少个map task: 2-切片是一个逻辑的概念,指的是文件中数据的偏移量范围: 3-切片的具体大小应该根据所处理的文件大小来 ...

  10. Docker技术入门与实战第2版-高清文字版

      Docker技术入门与实战第2版-高清文字版 下载地址https://pan.baidu.com/s/1bAoRQQlvBa-PXy5lgIlxUg 扫码下面二维码关注公众号回复100011 获取 ...