BZOJ3322[Scoi2013]摩托车交易——最大生成树+贪心+倍增
题目描述
输入
接下来的一行有n 个数,每个数均不相同,且值介于1 到n 之间,代表订单的顺序。
第三行有n 个数,第i 个数表示i 号城市的订单的上限额bi,bi 为正值表示该订单为买入交易(针对mzry1992 而言),上限为bi,bi 为负值表示该订单为卖出交易(同样针对mzry1992 而言)上限为 -bi。
接下来的m 行每行有三个数,u, v, w,表示城市u 和城市v 之间有一条载重上限为w 的高速公路,这里假定所有高速公路都是双向的,城市的序号是从1 到n 的。
输入的最后一行有q 个数,代表有列车站城市的序号。
对于20% 数据,n <= 100,m <= 200
对于50% 数据,n <= 3000,m <= 6000
对于100% 数据,1 <= n <= 10^5,n - 1 <= m <= 2*[1]10^5,0 <= q <= n,0 < |bi| < 10^9,0 < w < 10^9,保证任意两个城市之间是通过高速公路连通的。
输出
样例输入
3 3 2
2 3 1
-6 5 -3
1 3 5
2 3 2
2 1 6
1 3
Sample #2
4 4 0
1 2 3 4
5 4 -6 -1
1 2 4
2 3 100
3 4 1
4 1 4
样例输出
3
2
Sample #2
6
1
Hint
第一组样例:其中一种合法的方案是最初从2 号城市买入5 单位的黄金,先走第三条高速公路到1 号城市,然后再坐列车到3 号城市,在3 号城市卖出3 单位的黄金,然后乘坐列车到1 城市,在1 号城市卖出2 单位的黄金。
第二组样例:其中一种合法的方案是最初从1 号城市买入4 单位的黄金,走第一条高速公路,在2 号城市买入3 单位的黄金,走第二条高速公路,在三城市点卖出6 单位的黄金,走第三条高速公路,在4 号城市卖出1 单位的黄金。
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n,m,k,x;
ll INF=1e16;
int vis[100010];
int f[100010][20];
ll g[100010][20];
int d[100010];
int head[100010];
int to[200010];
int next[200010];
ll val[200010];
int fa[100010];
int cnt;
struct miku
{
int x;
int y;
ll v;
}a[500010];
ll v[100010];
int q[100010];
int tot;
ll now;
int find(int x)
{
if(fa[x]==x)
{
return x;
}
return fa[x]=find(fa[x]);
}
void add(int x,int y,ll z)
{
tot++;
next[tot]=head[x];
head[x]=tot;
to[tot]=y;
val[tot]=z;
}
bool cmp(miku a,miku b)
{
return a.v>b.v;
}
void dfs(int x,int fa)
{
d[x]=d[f[x][0]]+1;
for(int i=1;i<=18;i++)
{
f[x][i]=f[f[x][i-1]][i-1];
g[x][i]=min(g[x][i-1],g[f[x][i-1]][i-1]);
}
for(int i=head[x];i;i=next[i])
{
if(to[i]!=fa)
{
f[to[i]][0]=x;
g[to[i]][0]=val[i];
dfs(to[i],x);
}
}
}
ll lca(int x,int y)
{
ll res=INF+100;
if(d[x]<d[y])
{
swap(x,y);
}
int dep=d[x]-d[y];
for(int i=0;i<=18;i++)
{
if((dep&(1<<i)))
{
res=min(res,g[x][i]);
x=f[x][i];
}
}
if(x==y)
{
return res;
}
for(int i=18;i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
res=min(res,g[x][i]);
res=min(res,g[y][i]);
x=f[x][i];
y=f[y][i];
}
}
return min(res,min(g[x][0],g[y][0]));
}
int main()
{
memset(g,0x7f7f7f7f,sizeof(g));
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&q[i]);
}
for(int i=1;i<=n;i++)
{
scanf("%lld",&v[i]);
fa[i]=i;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%lld",&a[i].x,&a[i].y,&a[i].v);
}
cnt=m;
for(int i=1;i<=k;i++)
{
scanf("%d",&vis[i]);
}
for(int i=2;i<=k;i++)
{
cnt++;
a[cnt].x=vis[1];
a[cnt].y=vis[i];
a[cnt].v=INF;
}
sort(a+1,a+1+cnt,cmp);
for(int i=1;i<=cnt;i++)
{
int fx=find(a[i].x);
int fy=find(a[i].y);
if(fx!=fy)
{
fa[fx]=fy;
add(a[i].x,a[i].y,a[i].v);
add(a[i].y,a[i].x,a[i].v);
}
}
dfs(q[1],0);
if(v[q[1]]>0)
{
now=v[q[1]];
}
else
{
printf("0\n");
}
for(int i=1;i<n;i++)
{
ll lim=lca(q[i],q[i+1]);
now=min(now,lim);
if(v[q[i+1]]>0)
{
now+=1ll*v[q[i+1]];
}
else
{
printf("%lld\n",min(now,-v[q[i+1]]));
now=max(0ll,now+v[q[i+1]]);
}
}
}
BZOJ3322[Scoi2013]摩托车交易——最大生成树+贪心+倍增的更多相关文章
- 2019.03.28 bzoj3322: [Scoi2013]摩托车交易(kruskal重构树+贪心)
传送门 题意咕咕咕 思路: 先把所有可以列车通的缩成一个点,然后用新图建立kruskalkruskalkruskal重构树. 这样就可以倒着贪心模拟了. 代码: #include<bits/st ...
- BZOJ3322 : [Scoi2013]摩托车交易
求出最大生成树,则两点间的最大容量为树上两点间的边权的最小值. 设$lim[i]$表示第$i$个订单的城市允许携带的黄金上限,则 $lim[i]=\min(lim[i+1],a[i]和a[i+1]点间 ...
- [SCOI2013]摩托车交易 kruskal重构树(最大生成树) 倍增
---题面--- 题解: 这题想法简单,,,写起来真的是失智,找了几个小时的错误结果是inf没开到LL范围.... 首先我们需要找到任意两点之间能够携带黄金的上限值,因为是在经过的道路权值中取min, ...
- 【SCOI2013】摩托车交易 - 最大生成树+树链剖分
题目描述 mzry1992 在打完吊针出院之后,买了辆新摩托车,开始了在周边城市的黄金运送生意.在mzry1992 生活的地方,城市之间是用双向高速公路连接的.另外,每条高速公路有一个载重上限,即在不 ...
- 【[SCOI2013]摩托车交易 】
倍增什么的最慢了,常数太大了 我们可以上树剖啊 但是如果用树剖来查询树上两点之间的最小边权的话,可能只能在上一棵线段树? 那也太\(naive\)了,尽管倍增常数大,但是还是比两个\(log\)快的 ...
- [SCOI2013]摩托车交易 题解
思路分析 为了让交易额尽量大,显然我们需要尽量多地买入.对于每个城市,到达这个城市时携带的黄金受到几个条件的影响:之前卖出的黄金,之前能买入的最多的黄金,前一个城市到当前城市的路径上的最小边权.既然不 ...
- NOIP2013 货车运输(最大生成树,倍增)
NOIP2013 货车运输(最大生成树,倍增) A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道 ...
- NOIP2013 货车运输 (最大生成树+树上倍增LCA)
死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...
- [NOIP2013/Codevs3287]货车运输-最小[大]生成树-树上倍增
Problem 树上倍增 题目大意 给出一个图,给出若干个点对u,v,求u,v的一条路径,该路径上最小的边权值最大. Solution 看到这个题第一反应是图论.. 然而,任意路径最小的边权值最大,如 ...
随机推荐
- 【Topcoder 10384】KingdomMap
Topcoder 10384 题意:给你一个森林,求是否能将这个森林的点集分成两部分,每部分放在一列中,要求边是直的并且不能交叉,问最少删哪几条边. 思路:我们考虑森林中的一棵树,以\(u\)为根,将 ...
- Android 去掉ScrollView、GridView、ListView向上 滑动时顶部的投影/阴影
在ScrollView.GridView.ListView向上滑动的过程中,这些控件的顶部会出现一个系统默认的白色阴影,有些时候这个白色的阴影看上去好看,那么就需要除去. 去掉方法:在ScrollVi ...
- SkylineGlobe 移动端开发测试
基于SkylineGlobe提供的安卓版本SDK,在已有菜单中增加自定义内容,测试代码如下: 新增加文件ZhaoHeContainer.java package com.skyline.terraex ...
- python---pandas.merge使用
merge 函数参数 ”’ merge: 合并数据集, 通过left, right确定连接字段,默认是两个数据集相同的字段 参数 说明 left 参与合并的左侧DataFrame right 参与合并 ...
- angularjs的ng-change事件演示
今天练习angularjs的ng-change事件. 比如用户作出选择时,系统所指定的选项中,没有用户合适的选项.此时我们可以让用户填写. 刚开始文本框是隐藏的.当用户选择了checkbox之后才会显 ...
- nginx 安装问题
yum -y install xxx pcre-devel openssl-devel zlib-devel 这个三个包需要 有时候,我们需要单独安装nginx,来处理大量的下载请求.单独在 ...
- VS2017登陆不了,TFS无法连接成功的问题
由于使用的win7 64位操作系统,重装系统以后,安装了vs2017,登陆不成功,https://auth.gfx.ms/16.000.27887.2/OldConvergedLogin_PCore. ...
- Webpack 2 视频教程 002 - NodeJS 安装与配置
原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」. Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本讲 ...
- sql 某字段存储另一个表的多个id值并以逗号分隔,现根据id去中文并拼接同样以逗号分隔
首先介绍用到的两个函数 charindex(要查找的表达式1,表达式2),返回值为表达式1在表达式2中的下标,未找到则返回0.(sql的下标是从1开始的),例如 select charindex('s ...
- Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)-C-Bracket Subsequence
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> ...