题意

链接: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. YARN HA部署架构

    hadoop001: zk rm(zkfc线程) nm hadoop002: zk rm(zkfc线程) nm hadoop003: zk nm RMStateStore: 存储在ZK的/rmstor ...

  2. 自己用到的解决Python3.6.5+Django2.0集成xadmin后台点击添加或者内容详情报 list index out of range 的错误的办法如下:

    Python3.6.5 Django2.0 这是Django版本与xadmin兼容的问题 解决办法如下: 注释掉如下代码: def render(self, name, value, attrs=No ...

  3. Linux:FTP服务器的搭建

    FTP服务器的简介 系统用户 即系统本机的用户.Linux一般不会针对实体用户进行限制,因此实体用户可以针对整个文件 系统进行工作.但通常不希望他们通过FTP方式远程访问系统. 虚拟用户 只能采用FT ...

  4. Intellj IDEA 快捷键冲突

    Intellij IDEA快捷键冲突 [问题描述]: ctr + alt + 方向键 与系统的快捷键冲突,按快捷键,屏幕方向发生改变. [解决办法]: ctr + alt + F12 调用出Intel ...

  5. vue 指令和修饰符

    1. v-textv-text主要用来更新textContent,可以等同于JS的text属性. <spanv-text="msg"></span> 这两者 ...

  6. SourceTree3.2.6版本跳过注册办法

    一.去sourceTree官网下载最新的包 官网:https://www.sourcetreeapp.com/windows版下载地址:https://product-downloads.atlass ...

  7. 手摸手教你bootstrap定制

    老实说我一直不太喜欢使用bootstrap,bootstrap样式组件虽然丰富但实际开发使用到的不多:栅格系统虽然好用,满屏div也是看的头疼:所以当经理说要用bootstrap开发新项目的时候,我内 ...

  8. 直接命令行中执行PHP代码(PHP CLI模式)

    一般执行PHP代码,需要把PHP代码写成一个文件,但是有时候查一些PHP配置没有这个必要,能不能直接执行PHP代码呢? 答案是可以的. 在命令行下,采用CLI方式执行PHP代码,这里列出几个常用的命令 ...

  9. 链表中删除倒数第K个节点

    问题描述 分别实现两个函数,一个可以删除单链表中倒数第K个节点,另一个可以删除双链表中倒数第K个节点. 问题分析与解决 从问题当中,我们只能得到一个链表和要删除的第K个节点的信息,于是就有以下思路:如 ...

  10. Caused by: org.springframework.data.mapping.PropertyReferenceException: No property id found for type Users!

    Spring Data JPA自定义Repository Caused by: org.springframework.data.mapping.PropertyReferenceException: ...