HDU 4729 An Easy Problem for Elfness(树链剖分边权+二分)
题意
链接:https://cn.vjudge.net/problem/HDU-4729
给你n个点,然你求两个点s和t之间的最大流.而且你有一定的钱k,可以进行两种操作
1.在任意连个点之间建立一个单位1的流,费用a
2.将原先的流扩大1个单位,费用b
思路
题目已经说了是一棵树,那么树上两点的最大流就是两点路径上的最小值。其实两种操作各一次对最大流的贡献是相等的。我们分类讨论:
- 如果a<=b,直接算第一种方案即可,直接给s、t连一条边,对答案的贡献是k/a。
- 如果a>b,分两种情况。如果k>a,我们可以先操作一次方案一,即先给s、t连一条边,再对这条边进行扩大,这种方法对答案的贡献是(k-a)/b+1;如果k<=a,那么我们只扩大,肯定是先把最小的边扩大了,再看扩大新的最小边……直接暴力肯定不行,我们二分最大流x,我们可以扩大k/b次,那么判断一下在k/b次内能不能使得s到t的最小值>=x即可。具体实现我们可以递归处理,看代码。
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define int ll
#define il inline
const int inf = 0x3f3f3f3f, N = 1e5 + 5;
//适用于正负数,(int,long long,float,double)
template <class T>
il bool read(T &ret)
{
char c;
int sgn;
T bit=0.1;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
if(c==' '||c=='\n')
{
ret*=sgn;
return 1;
}
while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;
ret*=sgn;
return 1;
}
// 线段树
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
int n, M, T;
int head[N], tot;
int top[N]; // top[v]即v所在重链的顶端结点
int fa[N]; // 父节点
int deep[N]; // 深度
int num[N]; // num[v] 以v为根的子树结点数
int p[N]; // p[v]为v的dfs位置
int fp[N]; // 与p相反
int son[N]; // 重子编号
int pos;
int mi[N << 2],val[N];
void pushUp(int rt)
{
mi[rt] = min(mi[rt << 1], mi[rt << 1 | 1]);
}
void build(int l, int r, int rt)
{
mi[rt] = inf;
if (l == r)
{
mi[rt]=val[fp[l]];
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
pushUp(rt);
}
int query(int L, int R, int l, int r, int rt)
{
if (L <= l && r <= R)
return mi[rt];
int m = (l + r) >> 1;
int ret = inf;
if (L <= m) ret = min(ret, query(L, R, lson));
if (R > m) ret = min(ret, query(L, R, rson));
return ret;
}
void update(int p, int x, int l, int r, int rt)
{
if (l == r)
{
mi[rt] = x;
return;
}
int m = (r + l) >> 1;
if (p <= m) update(p, x, lson);
else update(p, x, rson);
pushUp(rt);
}
// 树链剖分
struct Edge
{
int to, next,w;
} edge[N * 2];
void init()
{
tot = 0;
pos = 0;
memset(head,-1,sizeof(head));
memset(son, -1,sizeof(son));
}
void add(int u, int v,int w)
{
edge[tot].to = v;
edge[tot].next = head[u];
edge[tot].w=w;
head[u] = tot++;
}
void dfs1(int u, int pre, int d)
{
deep[u] = d;
fa[u] = pre;
num[u] = 1;
for (int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if (v != pre)
{
val[v]=edge[i].w;
dfs1(v, u, d + 1);
num[u] += num[v];
if (son[u] == -1 || num[v] > num[son[u]])
son[u] = v;
}
}
}
void dfs2(int u, int sp)
{
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if (son[u] == -1)
return;
dfs2(son[u], sp);
for (int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if (v != son[u] && v != fa[u])
dfs2(v, v);
}
}
int queryMin(int u, int v)
{
int f1 = top[u], f2 = top[v];
int tmp = inf;
while (f1 != f2)
{
if (deep[f1] < deep[f2])
{
swap(f1, f2);
swap(u, v);
}
tmp = min(tmp, query(p[f1], p[u], 0, pos - 1, 1));
u = fa[f1];
f1 = top[u];
}
if (u == v) return tmp;
if (deep[u] > deep[v]) swap(u, v);
return min(tmp, query(p[son[u]], p[v], 0, pos - 1, 1));
}
int all=0;
bool fun(ll L,ll R,ll l,ll r,ll rt,ll x)
{
if(L<=l&&r<=R&&mi[rt]>=x)
{
return true;
}
if(l==r)
{
if(mi[rt]>=x)
return true;
all-=(x-mi[rt]);
return all>=0;
}
int m=(l+r)>>1;
if(R<=m)
{
return fun(L,R,lson,x);
}
else if(L>m)
{
return fun(L,R,rson,x);
}
else
return fun(L,m,lson,x)&&fun(m+1,R,rson,x);
}
bool check(ll u,ll v,ll x)
{
int f1 = top[u], f2 = top[v];
while (f1 != f2)
{
if (deep[f1] < deep[f2])
{
swap(f1, f2);
swap(u, v);
}
if(!fun(p[f1], p[u], 0, pos - 1, 1,x))
return false;
u = fa[f1];
f1 = top[u];
}
if (u == v) return true;
if (deep[u] > deep[v]) swap(u, v);
return fun(p[son[u]], p[v], 0, pos - 1, 1,x);
}
signed main()
{
read(T);
int cs=0;
while (T--)
{
init();
read(n),read(M);
for(int i=0; i<n-1; i++)
{
ll u,v,w;
read(u),read(v),read(w);
add(u,v,w);
add(v,u,w);
}
dfs1(1, 0, 0);
dfs2(1, 1);
build(0, pos - 1, 1);
printf("Case #%lld:\n",++cs);
while (M--)
{
ll s,t,k,a,b;
read(s),read(t),read(k),read(a),read(b);
ll ans=queryMin(s,t);
if(k<min(a,b))
{
printf("%lld\n",ans);
}
else if(a<=b)
{
ans+=k/a;
printf("%lld\n",ans);
}
else
{
if(k>a)
ans+=(k-a)/b+1;
ll l=ans,r=10000,mid;
while(l<=r)
{
mid=(l+r)>>1;
all=k/b;
if(check(s,t,mid))
{
ans=mid;
l=mid+1;
}
else
r=mid-1;
}
printf("%lld\n",ans);
}
}
}
return 0;
}
HDU 4729 An Easy Problem for Elfness(树链剖分边权+二分)的更多相关文章
- [HDU 5293]Tree chain problem(树形dp+树链剖分)
[HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...
- 数据结构(主席树):HDU 4729 An Easy Problem for Elfness
An Easy Problem for Elfness Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65535/65535 K (J ...
- HDU 4729 An Easy Problem for Elfness (主席树,树上第K大)
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove 题意:给出一个带边权的图.对于每一个询问(S , ...
- HDU 4729 An Easy Problem for Elfness(主席树)(2013 ACM/ICPC Asia Regional Chengdu Online)
Problem Description Pfctgeorge is totally a tall rich and handsome guy. He plans to build a huge wat ...
- HDU 4729 An Easy Problem for Elfness 主席树
题意: 给出一棵树,每条边有一个容量. 有若干次询问:\(S \, T \, K \, A \, B\),求路径\(S \to T\)的最大流量. 有两种方法可以增大流量: 花费\(A\)可以新修一条 ...
- 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)
Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- POJ2763 Housewife Wind 树链剖分 边权
POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...
随机推荐
- 转战物联网·基础篇08-例说MQTT协议各控制报文
前面讨论了MQTT协议的控制报文的格式,下面分别举例探讨各个控制报文的详细内容. 01.CONNECT – 连接服务端 客户端到服务端的网络连接建立后,客户端发送给服务端的第一个报文必须是CO ...
- luoguP1020 导弹拦截
题意 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国 ...
- Scrum会议(十周)
1.任务分配 2.会议内容探讨了本次取得的重大突破和后续要继续开展的工作.分析了自己在前端开发遇到的问题,以及如何优化自己的前端界面.然后分工,每人都去优化一部分界面,比如段祥负责个人中心的优化,程吉 ...
- 最小化MarkdownPad 2安装体积(win10)
一.原因 MarkdownPad2在Win10当中可能无法正常运行,右侧预览界面会出现错误"This view has crashed!"查阅官网FAQ得知大多数情况下安装Awes ...
- LG4158 「SCOI2009」粉刷匠 线性DP
问题描述 LG4158 题解 设\(opt[i][j][k]\)代表到\((i,k)\)刷了\(j\)次的方案数. 一开始DP顺序有点问题,调了很长时间. 务必考虑清楚DP顺序问题 \(\mathrm ...
- 第04组 Alpha冲刺(3/4)
队名:斗地组 组长博客:地址 作业博客:Alpha冲刺(3/4) 各组员情况 林涛(组长) 过去两天完成了哪些任务: 1.收集各个组员的进度 2.写博客 展示GitHub当日代码/文档签入记录: 接下 ...
- php处理curl的返回结果
最简单的方式: json_decode($res,true): 结果都是:
- 【CodeChef】Find a special connected block - CONNECT(斯坦纳树)
[CodeChef]Find a special connected block - CONNECT(斯坦纳树) 题面 Vjudge 题解 还是一样的套路题,把每个数字映射到\([0,K)\)的整数, ...
- 深入理解Java中的Garbage Collection
前提 最近由于系统业务量比较大,从生产的GC日志(结合Pinpoint)来看,需要对部分系统进行GC调优.但是鉴于以往不是专门做这一块,但是一直都有零散的积累,这里做一个相对全面的总结.本文只针对Ho ...
- 深入理解JVM,虚拟机类加载机制
类加载过程概览 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括以下7个阶段: 加载(Loading) 验证(Verification) 准备(Preparation) 解析(Re ...