【SCOI2013】摩托车交易 题解

news/2025/4/2 6:15:21/

【SCOI2013】摩托车交易

Description

mzry1992 在打完吊针出院之后,买了辆新摩托车,开始了在周边城市的黄金运送生意。
在mzry1992 生活的地方,城市之间是用双向高速公路连接的,另外,每条高速公路有一个载重上限,即在不考虑驾驶员和摩托车重量的情况下,如果所载货物的量超过某个值,则不能驶上该条高速公路。
今年,mzry1992 一共收到了来自n个不同城市的n份定订单,每个订单要求卖出上限为一定量的黄金,或是要求买入上限为一定量的黄金。由于订单并不是同时发来的,为了维护生意上的名声,mzry1992 不得不按照订单发来的顺序与客户进行交易。
他与第i客户进行交易的具体步骤是:
1.前往第i个客户所在城市。当然,中途是完全允许经过其他城市的。
2.与第i个客户进行交易。
但有两个限制:
(a) 与最后一个客户完成交易后,手上没有剩余黄金。
(b) 由于黄金是很贵重的物品,不能出现因为买入过多黄金而造成在以后的运送过程中不得不丢弃黄金的情况。
mzry希望总交易额最大,其次他希望卖出交易额序列的字典序最大。其中字典序指的是先比较第一次卖出交易额,若相等则比较下一次,以此类推。
一开始,mzry1992 位于第一个订单客户所在的城市。
现在有一个好消息,有人提供了mzry1992 免费试用周边城市的列车系统的资格。具体来讲,如果mzry1992希望从A 城市到达B 城市,且A、B 城市均有列车站的话,他可以携带着黄金与摩托车从A 城市乘坐列车到B 城市,这里假定乘坐列车没有载重限制。
现在已知城市间的交通系统情况和订单情况,请帮助mzry1992 计算每个向mzry1992 购买黄金的客户的购买量。

Input

输入的第一行有三个整数n, m, q,分别表示城市数,连通城市的高速公路数和有列车站的城市数。
接下来的一行有n 个数,每个数均不相同,且值介于1 到n 之间,代表订单的顺序。
第三行有n 个数,第i 个数表示i 号城市的订单的上限额bi,bi 为正值表示该订单为买入交易(针对mzry1992 而言),上限为bi,bi 为负值表示该订单为卖出交易(同样针对mzry1992 而言)上限为-bi。
接下来的m 行每行有三个数,u, v, w,表示城市u 和城市v 之间有一条载重上限为w 的高速公路,这里假定所有高速公路都是双向的,城市的序号是从1 到n 的。
输入的最后一行有q 个数,代表有列车站城市的序号。

Output

按照订单顺序对于每个卖出交易,输出一行,该行只有一个整数x,表示卖出黄金的量。

Sample Input

输入1:
3 3 2
2 3 1
-6 5 -3
1 3 5
2 3 2
2 1 6
1 3
输入2:
4 4 0
1 2 3 4
5 4 -6 -1
1 2 4
2 3 100
3 4 1
4 1 4

Sample Output

输出1:
3
2
样例解释1:
其中一种合法的方案是最初从2 号城市买入5 单位的黄金,先走第三条高速公路到1 号城市,然后再坐列车到3 号城市,在3 号城市卖出3 单位的黄金,然后乘坐列车到1 城市,在1 号城市卖出2 单位的黄金。
输出2:
6
1
样例解释2:
其中一种合法的方案是最初从1 号城市买入4 单位的黄金,走第一条高速公路,在2 号城市买入3 单位的黄金,走第二条高速公路,在三城市点卖出6 单位的黄金,走第三条高速公路,在4 号城市卖出1 单位的黄金。

Data Constraint

对于20% 数据,n<=100,m<=200
对于50% 数据,n<=3000,m<=6000
对于100% 数据,1<=n<=105,n-1<=m<=2*105,0<=q<=n,0<|bi|<109,0<w<109,保证任意两个城市之间是通过高速公路连通的。

题解

显然,这题的买卖黄金过程很用模拟就可以实现,关键是可以买卖多少
首先需要明确一点,就是我们不一定要按照题目说的不能丢弃黄金,其实可以全部买完,之后在过不去路的时候再丢掉,这样子是对答案没有影响的
然后买卖黄金的过程就相当于是一个贪心了,需要买的城市全部买来,需要卖的城市能卖多少卖多少
下一个重要点就是找到一个城市到另一个城市中负重最小的边(因为两个城市间可以携带的黄金的量是由负重最小的那条边决定的),然后因为要运尽量多黄金,所以我们就要让最小的那条边的负重最大
所以我们可以想到什么?最大生成树!
于是我们只要保留原图中属于最生成树的边即可(至于列车站怎么连边,其实只要相邻地连过来就行了,因为最后形成的是一棵树)
接着,要在树上找到路径边权的最小值就随便用什么方法找都行了,可以用求LCA的方式,我用的是倍增,大佬用树剖和Tarjan也行

CODE

#include<cstdio>
#include<string>
#include<cmath>
#include<algorithm>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define swap(a,b) (a)^=(b)^=(a)^=(b)
#define R register ll
#define N 100005
#define M 300005
#define ll long long
#define inf 100000000000
using namespace std;
struct arr{ll u,v,w;}bian[M];
struct G{ll to,next,w;}e[N<<1];
ll n,m,q,go[N],train[N],tot,fa[N],cnt,f[N][20],dep[N],mxdep,head[N],b[N],g[N][20];;
inline void read(ll &x)
{x=0;ll f=1;char ch=getchar();while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();x*=f;
}
inline bool cmp(arr x,arr y) {return x.w>y.w;}
inline void add(ll u,ll v,ll len)
{e[++cnt].to=v;e[cnt].w=len;e[cnt].next=head[u];head[u]=cnt;
}
inline void dfs(ll u,ll fa)
{for (R i=head[u];i;i=e[i].next){ll v=e[i].to;if (v==fa) continue;f[v][0]=u;g[v][0]=e[i].w;dep[v]=dep[u]+1;mxdep=max(dep[v],mxdep);dfs(v,u);}
}
inline ll lca(ll x,ll y)
{ll mn=inf;if (dep[x]!=dep[y]){if (dep[x]<dep[y]) swap(x,y);for (R i=log2(dep[x]-dep[y]);i>=0;--i)if (dep[f[x][i]]>dep[y]) mn=min(g[x][i],mn),x=f[x][i];mn=min(g[x][0],mn);x=f[x][0];	}if (x==y) return mn;for (R i=log2(dep[x]);i>=0;--i)if (f[x][i]!=f[y][i]) mn=min(mn,min(g[x][i],g[y][i])),x=f[x][i],y=f[y][i];mn=min(mn,min(g[x][0],g[y][0]));return mn; 
}
inline ll find(ll k)
{if (fa[k]==k) return k;return fa[k]=find(fa[k]);
}
int main()
{read(n);read(m);read(q);for (R i=1;i<=n;++i)read(go[i]),fa[i]=i;for (R i=1;i<=n;++i)read(b[i]);for (R i=1;i<=m;++i)read(bian[i].u),read(bian[i].v),read(bian[i].w);for (R i=1;i<=q;++i){read(train[i]);if (i>1) bian[++m].u=train[i-1],bian[m].v=train[i],bian[m].w=inf;}sort(bian+1,bian+1+m,cmp);ll tot=1;for (R i=1;i<=m;++i){ll f1=find(bian[i].u),f2=find(bian[i].v);if (f1!=f2){add(bian[i].u,bian[i].v,bian[i].w);add(bian[i].v,bian[i].u,bian[i].w);++tot;fa[f1]=f2;if (tot==n) break;}}mxdep=1;dep[1]=1;dfs(1,0);for (R j=1;j<=log2(mxdep);++j)for (R i=1;i<=n;++i)f[i][j]=f[f[i][j-1]][j-1],g[i][j]=min(g[i][j-1],g[f[i][j-1]][j-1]);ll now=go[1];tot=0;if (b[go[1]]>0) tot=b[go[1]];else printf("0\n");for (R i=2;i<=n;++i){ll k=lca(go[i-1],go[i]);if (tot>k) tot=k;if (b[go[i]]>0) tot+=b[go[i]];else{printf("%lld\n",min(-b[go[i]],tot));tot-=min(-b[go[i]],tot);}}return 0;
}

http://www.ppmy.cn/news/277380.html

相关文章

【历史上的今天】9 月 25 日:谷歌进军电商行业;摩托罗拉诞生;神舟七号发射成功

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2021 年 9 月 25 日&#xff0c;伟大的文学家鲁迅诞生在 140 年前的今天&#xff0c;他是 20 世纪的文化巨人&#xff0c;以文字为武器&#xff0c;奠基了现代文学&…

挖掘:如何用迅雷下载4399小游戏站内的所有游戏

偶然一次无聊想玩玩flash小游戏&#xff0c;于是就百度了一下&#xff0c;随意进了一个网站--4399&#xff0c;然后漫无目的瞎看&#xff0c;点了一个叫特技摩托3的小游戏&#xff0c;不玩不知道&#xff0c;一玩就从此爱不释手&#xff0c;可是每次玩都要打开网页&#xff0c;…

115 摩托车

问题描述 : 明明是一家摩托车厂的老板&#xff0c;他的厂为了迎合市场中不同消费者的需求&#xff0c;会生产不同型号的摩托车&#xff0c;这为明明的厂带来了不小的收益。有一次&#xff0c;一位大客户来到明明的厂洽谈生意&#xff0c;他需要采购一批型号各不相同的摩托车&a…

特技摩托前线android安装_特技摩托前线安卓版下载_特技摩托前线手游下载v3.8.0_3DM手游...

《特技摩托前线》是一款十分好玩的特技摩托游戏&#xff0c;在游戏中你将要努力的寻找到摩托车的平衡点&#xff0c;这样你才能完美的操控你的摩托车去完成每项特技动作&#xff0c;喜欢就赶快下载体验吧&#xff01; 游戏详情 我们用了数年的时间来制作这个智能手机上最好的竞…

特技摩托前线android安装_特技摩托前线下载-特技摩托前线下载v6.8.0 安卓版-西西安卓游戏...

特技摩托前线是很老的一款产品&#xff0c;这款游戏早在几年前就已经发售&#xff0c;但是在现在看来它四号的不过时&#xff0c;你照样可以在这款2D的竞速游戏当中感受到不一样的飞跃体验&#xff0c;通过自己的操作在各个场地当中不断的进行飞跃&#xff0c;感兴趣的话可以来…

暴力摩托

Description N个站&#xff0c;之间连了M条双向的通路&#xff01;但每条路都规定了一个速度的限制值&#xff0c;在这条路上必须以这个速度前进&#xff01;所以在 前进的时候要调整速度&#xff0c;现决定尽量使调整的幅度小一些&#xff0c;也就是使走过的路的速度最大值与…

特技摩托前线android安装_特技摩托前线手游|特技摩托前线安卓版下载_v3.80_9ht安卓下载...

《特技摩托之前线(Trials Frontier)》是以竞技为主&#xff0c;反正小编的技术是在第一关也是折腾了好长时间&#xff0c;总是找不到合适平衡点&#xff0c;在一个就是育碧的这个游戏之前以前在ios发布了&#xff0c;评价也是相当高&#xff0c;育碧的游戏还是蛮不错的&#xf…

特技摩托前线android安装_特技摩托前线修改中文版-特技摩托前线全摩托解锁版下载7.9.1安卓版-玩友游戏网...

特技摩托前线全摩托解锁版是一款摩托车闯关竞速游戏&#xff0c;在游戏中我们可以驾驶摩托车和其他的对手进行比赛竞速&#xff0c;我们需要不断的挑战更多的关卡和场景&#xff0c;让自己拥有更快的速度。我们在途中许多跨过许多陡峭的地形&#xff0c;在翻转的时候要保持车的…