题目描述

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. swagger -- 前后端分离的API接口

    文章目录 一.背景 二.swagger介绍 三.在maven+springboot项目中使用swagger 四.swagger在项目中的好处 五.美化界面 参考链接:5分钟学会swagger配置 参考 ...

  2. 新阿里云服务器从0开始配置为python开发环境

    由于每次打开linux虚拟机比较麻烦,于是尝试一下云服务器,在阿里云领取了一个月的试用服务器,这里记录一下新服务器从0配置成python开发环境的步骤,以便以后配置新服务器时有个参考. 免费领取一个月 ...

  3. WEB简单的登录注册功能(分层)

    登录: 前端页面: <body> <form action="/webtext/LogingServlet" method="post"> ...

  4. 微服务迁移记(五):WEB层搭建(5)-集成ueditor编辑器,伪分布式图片上传

    一.redis搭建 二.WEB层主要依赖包 三.FeignClient通用接口 以上三项,参考<微服务迁移记(五):WEB层搭建(1)> 四.SpringSecurity集成 参考:< ...

  5. Day13_商品详情及静态化

    学于黑马和传智播客联合做的教学项目 感谢 黑马官网 传智播客官网 微信搜索"艺术行者",关注并回复关键词"乐优商城"获取视频和教程资料! b站在线视频 0.学习 ...

  6. 二手99新iPhone8Plus有锁移动联通版

    原文是维基百科:http://www.bosimedia.com/wiki/IPhone_8#cite_note-1 iPhone8Plus详细介绍 iPhone 8与iPhone 8 Plus 是苹 ...

  7. Python列表截取

    Python列表截取: 使用索引下标查看列表元素: lst = ['a','b','c','d','e','f','g','h'] print(lst[0]) # a print(lst[3]) # ...

  8. 遍历多个 txt 文件进行获取值

    import random def load_config(path): with open(path,'r') as tou: return [line for line in tou.readli ...

  9. PHP array_fill_keys() 函数

    ------------恢复内容开始------------ 实例 用给定的指定键名的键值填充数组: <?php$keys=array("a","b",& ...

  10. luogu P4725 多项式对数函数(多项式 ln)

    LINK:多项式对数函数 多项式 ln 如题 是一个模板题.刚学会导数 几个知识点 \([f(x)\cdot g(x)]'=f(x)'g(x)+f(x)g(x)',f(g(x))'=f'(g(x))g ...