USACO December 铂金Maxflow
USACO 2015 December Contest, Platinum
Problem 1. Max Flow
Farmer John has installed a new system of N−1 pipes to transport milk between the N stalls in his barn (2≤N≤50,000 ), conveniently numbered 1…N . Each pipe connects a pair of stalls, and all stalls are connected to each-other via paths of pipes.
FJ is pumping milk between K pairs of stalls (1≤K≤100,000 ). For the i th such pair, you are told two stalls si and ti , endpoints of a path along which milk is being pumped at a unit rate. FJ is concerned that some stalls might end up overwhelmed with all the milk being pumped through them, since a stall can serve as a waypoint along many of the K paths along which milk is being pumped. Please help him determine the maximum amount of milk being pumped through any stall. If milk is being pumped along a path from si to ti , then it counts as being pumped through the endpoint stalls si and ti , as well as through every stall along the path between them.
INPUT FORMAT (file maxflow.in):
The first line of the input contains N and K .
The next N−1 lines each contain two integers x and y (x≠y ) describing a pipe between stalls x and y .
The next K lines each contain two integers s and t describing the endpoint stalls of a path through which milk is being pumped.
OUTPUT FORMAT (file maxflow.out):
An integer specifying the maximum amount of milk pumped through any stall in the barn.
SAMPLE INPUT:
5 10
3 4
1 5
4 2
5 4
5 4
5 4
3 5
4 3
4 3
1 3
3 5
5 4
1 5
3 4
SAMPLE OUTPUT:
9
Problem credits: Brian Dean
译:
农夫约翰已经安装了N-1个管道系统给N(2≤N≤50,000)个摊位输送牛奶,方便编号为1... N。每个管道连接一对摊位,所有的摊位都通过管道路径连接起来。
FJ在K对点(1≤K≤100,000)之间抽取牛奶。对于第i个这样的对,你被告知两个点Si和Ti,表示抽取牛奶路径的两个端点,这一路径上都是同一个单位的费率。 FJ关注的是,一些点最终可能会被所有抽取的牛奶通过。请帮助他确定所有点可能通过的最多的牛奶量。如果牛奶正在沿着路径Si到Ti,则认为它将通过端点Si和Ti,以及通过沿它们之间的路径中的每个点。
INPUT FORMAT (file maxflow.in):
The first line of the input contains N and K.
第一行两个整数N和K
The next N−1 lines each contain two integers x and y (x≠y) describing a pipe between stalls x and y.
接下来N-1行,每行两个整数X和Y,描述被一个管子连接的两个点X和Y
The next K lines each contain two integers s and t describing the endpoint stalls of a path through which milk is being pumped.
接下来K行,每行两个整数 S和T,描述正在被抽取牛奶所在的两个端点
OUTPUT FORMAT (file maxflow.out):
An integer specifying the maximum amount of milk pumped through any stall in the barn.
输出一个整数,表示通过任意点所能抽取的最大牛奶数量。
树上查分
拿到这题第一反应显然是树剖。。但实际上有更加方便的做法,那就是树上差分。
首先我们联想一下对数列进行差分的做法。序列差分这个技巧一般适用于:执行若干次区间加减,到最后再统计每个点的权值。设T是A的差分序列,我们把将a~b这个区间中的每个点加上c的操作(A[i]+=c a<=i<=b)转变成对T的操作T[a]+=c,T[b+1]-=c,最后A[k]的值就是Sum{T[i]}(1<=i<=k)即T的一个前缀和。这个很容易能理解,随便在脑中yy一下或者画画图都能理解。
然后我们再来看下这道题。这道题与序列上有一定相似之处:执行若干次路径上的加减,最后统计每个点的权值。我们可以将在序列上进行差分的方法拓展到树上。对于s~t这个路径上每个点加上c的操作,我们可以对树A的“差分树”T进行操作:T[s]+=c,T[t]+=c,T[LCA(s,t)]-=c,T[Father[LCA(s,t)]]-=c。即给s这个点加上c,给t这个店加上c,给s和t的最近公共祖先和这个祖先的父亲减去c。最后每个点的权值就是这个点的子树权值之和。
这样做为什么是正确的呢?我们来yy一下一般情况:对于一棵树,从s走到t可以这么走:先从s走到LCA(s,t),再从t走到LCA(s,t)。为了更方便接下来的叙述,我们可以想象有两个人分别从s和t走到LCA(s,t)。然后,我们要将路径s~t上每个点加上c,因为我们最后统计的是每个点的子树权值之和,所以说白了就是这个标记要向它的父亲上传;所以当我们给s和t都加上c后,上传到LCA(s,t)的时候就变成了2c,显然在这里是要减去c的;而对于LCA(s,t)的父亲,由于LCA(s,t)的标记也要上传,所以在LCA(s,t)的父亲处再减去一个c。这段话比较长,但是只要深刻理解数列差分的技巧,理解树上差分也是很容易的。
最后说几个实现上的细节。
第一,对于LCA(s,t),如果它是根,那么就没有将它父亲减去c的操作了。
第二,最后子树统计的时候的方法比较多。可以用类似拓扑排序的思想,从最后一层结点“逐层上传”。也可以用树型dp。这个随个人喜好而定。
具体看代码~
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#define maxn 50010
#define maxk 100010
using namespace std;
int n,k,s,t,tot,lca,root=,ans=,f[maxn],deep[maxn],value[maxn],head[maxn],p[maxn][];
struct node{
int go,next;
}e[maxk];
inline int read(){
int x=,f=;char ch=getchar();
while (ch>'' || ch<''){if (ch=='-') f=-;ch=getchar();}
while (ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void addedge(int &s,int &t){
e[++tot]=(node){t,head[s]};head[s]=tot;
e[++tot]=(node){s,head[t]};head[t]=tot;
}
void make_tree(int u,int fa){
int v;
for (int i=head[u];i;i=e[i].next){
v=e[i].go;
if (v!=fa){
deep[v]=deep[u]+;
f[v]=u;
make_tree(v,u);
}
}
}
void prepare(){
memset(p,-,sizeof(p));
for (int i=;i<=n;i++) p[i][]=f[i];
for(int j=;(<<j)<=n;j++)
for (int i=;i<=n;i++)
if (p[i][j-]!=-) p[i][j]=p[p[i][j-]][j-];
}
inline int LCA(int a,int b){
if (deep[a]<deep[b]) swap(a,b);
int t=trunc(log2(deep[a]));
for (int i=t;i>=;i--) if (deep[a]-(<<i)>=deep[b]) a=p[a][i];
if (a==b) return a;
for (int i=t;i>=;i--)
if (p[a][i]!=- && p[a][i]!=p[b][i]) a=p[a][i],b=p[b][i];
return p[a][];
}
int ask(int x){
for (int i=head[x];i;i=e[i].next){
if (f[x]!=e[i].go){
ask(e[i].go);
value[x]+=value[e[i].go];
}
}
ans=max(ans,value[x]);
}
int main(){
// freopen("maxflow.in","r",stdin);
// freopen("maxflow.out","w",stdout);
n=read();k=read();
for (int i=;i<n;i++){
s=read();t=read();
addedge(s,t);
}
deep[root]=;
make_tree(root,f[root]=);
prepare();
for (int i=;i<=k;i++){
s=read();t=read();
lca=LCA(s,t);
value[s]++;value[t]++;value[lca]--;value[f[lca]]--;
}
ask(root);
printf("%d\n",ans);
}
USACO December 铂金Maxflow的更多相关文章
- Usaco 2019 Jan Platinum
Usaco 2019 Jan Platinum 要不是昨天老师给我们考了这套题,我都不知道usaco还有铂金这么一级. 插播一则新闻:杨神坚持认为铂金比黄金简单,原因竟是:铜 汞 银 铂 金(金属活动 ...
- USACO 2015 December Contest, Gold Problem 2. Fruit Feast
Problem 2. Fruit Feast 很简单的智商题(因为碰巧脑出来了所以简单一,一 原题: Bessie has broken into Farmer John's house again! ...
- USACO 2015 December Contest, Platinum Problem Max Flow【树链剖分】
题意比较难理解,就是给你n个点的树,然后给你m个修改操作,每一次修改包括一个点对(x, y),意味着将x到y所有的点权值加一,最后问你整个树上的点权最大是多少. 比较裸的树链剖分了,感谢Haild的讲 ...
- USACO 2019 December Contest 随记
Forewords 今年 USACO 的比赛变化挺大的,有部分分了,而且不再是固定十个点了(部分分只说这几个点满足这几个性质,以为十个点的我还高兴了一会,一提交,...),除此之外居然赛后还排名了.这 ...
- [USACO 2018 December Contest]作业总结
t1 Convention 题目大意 每一头牛都有一个来的时间,一共有\(n\)辆车,求出等待时间最长的那头牛等待的最小时间. 解法 第一眼看到这道题还以为是\(2018noip\)普及组的t3魔鬼题 ...
- USACO 2012 December ZQUOJ 24122 Scrambled Letters(二分)
题意:有一个字典序名单,现在把这些名单的顺序和名字的字符顺序扰乱了,要输出原先的名字在原来的名单中的最低和最高位置. 分析:先将所有的名字串按字典序从小到大和从大到小分别排序smin[]和smax[] ...
- USACO 2012 December ZQUOJ 24128 Wifi Setup(动态dp)
题意:给出在同一条直线上的n个点和两个数A,B,现在要在这条直线上放置若干个信号塔,每个信号塔有一个r值,假设它的位置是x,则它能覆盖的范围是x-r~x+r,放置一个信号塔的花费是A+B*r,问要覆盖 ...
- USACO 铂金 T1
题意 给出一个数轴,每次可以选择停下并得到当前点的收益,或者继续随机向左右游走,走到边界游戏结束收益为0. 求从每个点出发的最大期望收益.(n<=1e5) 有一个显然的dp方程 这个方程是带环的 ...
- [Poj3261] [Bzoj1717] [后缀数组论文例题,USACO 2006 December Gold] Milk Patterns [后缀数组可重叠的k次最长重复子串]
和上一题(POJ1743,上一篇博客)相似,只是二分的判断条件是:是否存在一段后缀的个数不小于k #include <iostream> #include <algorithm> ...
随机推荐
- 博客写作的Checklist
Checklist 1.不要发明术语. 2.不要使用指代不清的代词.如:我,他. 3.不要使用错误的承前省. 4.不要使用口语. 5.给出结论之前,先交代背景. 6.站立会议报告中应有燃尽图. 7.燃 ...
- DHT
DHT(Distributed Hash Table,分布式哈希表)类似Tracker的根据种子特征码返回种子信息的网络.DHT全称叫分布式哈希表(Distributed Hash Table),是一 ...
- DOM-查找和修改
1. 查找: 按HTML查找: 问题: 每次只能按一个条件查找,如果查找条件复杂,则步骤很繁琐 解决: 选择器: 按选择器查找: 2个API 1. 只查找一个元素: var elem=parent.q ...
- hdu6069 多校Counting Divisors
思路:对于n^k其实就是每个因子的个数乘了一个K.然后现在就变成了求每个数的每个质因子有多少个,但是比赛的时候只想到sqrt(n)的分解方法,总复杂度爆炸,就一直没过去,然后赛后看官方题解感觉好妙啊! ...
- mysqldb mysql_config
在安装mysqldb Python的时候会用到mysql_config,但是正常安装的MySQL环境下是没有这个文件的,这个文件在Linux下是可执行文件,所以需要到mysql官方网站上下载MySQL ...
- 使用thymeleaf一旦没有闭合标签就会报错怎么解决
问题:input标签未关闭报bug,代码稍有不慎就出小问题 使用springboot的thymeleaf模板时默认会对HTML进行严格的检查,导致当你的标签没有闭合时就会通不过,例如: //要想通过, ...
- 2019.01.17 bzoj2333: [SCOI2011]棘手的操作(启发式合并)
传送门 启发式合并菜题. 题意:支持与连通块有关的几种操作. 要求支持连边,单点修改,连通块修改,全局修改和单点查值,连通块查最大值和全局最大值. 我们对每个连通块和答案用可删堆维护最大值,然后用启发 ...
- 分分钟搞懂rank() over(partition by)的使用
一.rank() over(partition by ...order by) 解释:partition by用于给结果集分组,如果没有指定那么它把整个结果集作为一个分组. 二.语法:ROW_NUM ...
- IntelliJ IDEA使用心得之Maven项目篇
今天和大家分享下,在IDEA中打开Maven项目的方法. 对于新版的IDEA可以直接打开Maven项目,但是对于旧版的IDEA需要使用Maven命令生成项目的IDEA配置文件. 在项目的根目录(即po ...
- max10之pll时钟源切换
问题3:PLL切换功能中,多次切换可能造成PLL锁不定 从现象看clkbadx信号是不影响的,但locked信号一定是有影响的.