题意

链接:https://cn.vjudge.net/problem/HDU-4729

给你n个点,然你求两个点s和t之间的最大流.而且你有一定的钱k,可以进行两种操作

1.在任意连个点之间建立一个单位1的流,费用a

2.将原先的流扩大1个单位,费用b

思路

题目已经说了是一棵树,那么树上两点的最大流就是两点路径上的最小值。其实两种操作各一次对最大流的贡献是相等的。我们分类讨论:

  1. 如果a<=b,直接算第一种方案即可,直接给s、t连一条边,对答案的贡献是k/a。
  2. 如果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(树链剖分边权+二分)的更多相关文章

  1. [HDU 5293]Tree chain problem(树形dp+树链剖分)

    [HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...

  2. 数据结构(主席树):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 ...

  3. HDU 4729 An Easy Problem for Elfness (主席树,树上第K大)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题意:给出一个带边权的图.对于每一个询问(S , ...

  4. 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 ...

  5. HDU 4729 An Easy Problem for Elfness 主席树

    题意: 给出一棵树,每条边有一个容量. 有若干次询问:\(S \, T \, K \, A \, B\),求路径\(S \to T\)的最大流量. 有两种方法可以增大流量: 花费\(A\)可以新修一条 ...

  6. 计蒜客 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 ...

  7. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...

  8. POJ3237 Tree 树链剖分 边权

    POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...

  9. POJ2763 Housewife Wind 树链剖分 边权

    POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...

随机推荐

  1. USB免驱RFID读写器编程解析之一:智能卡篇

    随着RFID应用的普及,越来越多的软件工程师需要使用RFID读写器编程来实现自己的需求.为了使软件工程师更快的了解RFID读写器的使 用,本文选择一款市面上常用的USB免驱RFID读写器SDT-HA来 ...

  2. DevOps VS 职责分离

    原文地址: https://medium.com/@jeehad.jebeile/devops-and-segregation-of-duties-9c1a1bea022e 原文作者:Jeehad J ...

  3. 27-限制容器的 Block IO

    Block IO 是另一种可以限制容器使用的资源.Block IO 指的是磁盘的读写,docker 可通过设置权重.限制 bps 和 iops 的方式控制容器读写磁盘的带宽,下面分别讨论. 注:目前 ...

  4. android binder 进程间通信机制5-Service注册和代理对象的获取

    ServiceManager,其实也是一个Service,不过它的Server端实现并未使用Binder库的结构实现,而是直接打开binder/dev进行通信的,不具有普遍性. 下面以MediaSer ...

  5. HashMap与HashTable的区别和理解

    Hashmap的理解 1:HashMap是基于哈希表的Map接口的非同步实现.此实现提供所有可选的映射操作,并允许使用null值和null键.HashMap储存的是键值对,HashMap很快.此类不保 ...

  6. go语言设计模式之Concurrency future

    future.go package future type SuccessFunc func(string) type FailFunc func(error) type ExecuteStringF ...

  7. 面向对象程序设计(JAVA) 第15周学习指导及要求

    2019面向对象程序设计(Java) 第15周学习指导及要求(2019.12.6-2019.12.13)   学习目标 (1) 掌握菜单组件用途及常用API: (2) 掌握对话框组件用途及常用API: ...

  8. vue项目中引入特殊字体

    特殊字体指的是默认电脑中没有的 1.下载字体 2.新建文件夹font,把字体放进去 3.新建font.css 4.使用@font-face设置字体 @font-face { font-family: ...

  9. MacOS命令行打包+签名+公证+生成dmg文件

    关于dmg文件是什么,和为什么要进行公证? 简单说下,dmg文件就是一个可直接在mac上安装的安装包,我自己的理解是就像windows上的exe安装包一样: 公证是将app传到苹果商店去做认证,如果不 ...

  10. Java 集成速卖通开发.

    一.申请成为开发者 申请入口:http://isvhz.aliexpress.com/isv/index.htm 说明文档:http://activities.aliexpress.com/open/ ...