BZOJ4390: [Usaco2015 dec]Max Flow
BZOJ4390: [Usaco2015 dec]Max Flow
Description
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 KK pairs of stalls (1≤K≤100,000). For the iith such pair, you are told two stalls sisi and titi, 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 KK 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 sisi to titi, then it counts as being pumped through the endpoint stalls sisi and titi, as well as through every stall along the path between them.
给定一棵有N个点的树,所有节点的权值都为0。
有K次操作,每次指定两个点s,t,将s到t路径上所有点的权值都加一。
请输出K次操作完毕后权值最大的那个点的权值。
Input
The first line of the input contains NN and KK.
The next N−1 lines each contain two integers x and y (x≠y,x≠y) describing a pipe between stalls x and y.
The next K lines each contain two integers ss and t describing the endpoint stalls of a path through which milk is being pumped.
Output
An integer specifying the maximum amount of milk pumped through any stall in the barn.
Sample Input
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
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 50010
using namespace std;
int n,m,c=1,d=1;
int head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],top[MAXN];
struct node1{
int next,to;
}a[MAXN<<1];
struct node2{
int data,c,l,r;
}b[MAXN<<2];
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
namespace ST{
#define LSON rt<<1
#define RSON rt<<1|1
#define DATA(x) a[x].data
#define SIGN(x) a[x].c
#define LSIDE(x) a[x].l
#define RSIDE(x) a[x].r
#define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
struct Segment{
int data,c,l,r;
}a[MAXN<<2];
inline void pushup(int rt){
DATA(rt)=max(DATA(LSON),DATA(RSON));
}
inline void pushdown(int rt){
if(!SIGN(rt)||LSIDE(rt)==RSIDE(rt))return;
SIGN(LSON)+=SIGN(rt);DATA(LSON)+=SIGN(rt);
SIGN(RSON)+=SIGN(rt);DATA(RSON)+=SIGN(rt);
SIGN(rt)=0;
}
void buildtree(int l,int r,int rt){
int mid;
LSIDE(rt)=l;
RSIDE(rt)=r;
if(l==r){
DATA(rt)=0;
return;
}
mid=l+r>>1;
buildtree(l,mid,LSON);
buildtree(mid+1,r,RSON);
pushup(rt);
}
void update(int l,int r,int c,int rt){
int mid;
if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
SIGN(rt)+=c;DATA(rt)+=c;
return;
}
pushdown(rt);
mid=LSIDE(rt)+RSIDE(rt)>>1;
if(l<=mid)update(l,r,c,LSON);
if(mid<r)update(l,r,c,RSON);
pushup(rt);
}
int query(int l,int r,int rt){
int mid,ans=0;
if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return DATA(rt);
pushdown(rt);
mid=LSIDE(rt)+RSIDE(rt)>>1;
if(l<=mid)ans=max(ans,query(l,r,LSON));
if(mid<r)ans=max(ans,query(l,r,RSON));
return ans;
}
void work_add(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
update(id[top[x]],id[x],1,1);
x=fa[top[x]];
}
if(deep[x]>deep[y])swap(x,y);
update(id[x],id[y],1,1);
return;
}
}
inline void add(int x,int y){
a[c].to=y;a[c].next=head[x];head[x]=c++;
a[c].to=x;a[c].next=head[y];head[y]=c++;
}
void dfs1(int rt){
son[rt]=0;size[rt]=1;
for(int i=head[rt];i;i=a[i].next){
int will=a[i].to;
if(!deep[will]){
deep[will]=deep[rt]+1;
fa[will]=rt;
dfs1(will);
size[rt]+=size[will];
if(size[son[rt]]<size[will])son[rt]=will;
}
}
}
void dfs2(int rt,int f){
id[rt]=d++;top[rt]=f;
if(son[rt])dfs2(son[rt],f);
for(int i=head[rt];i;i=a[i].next){
int will=a[i].to;
if(will!=fa[rt]&&will!=son[rt])
dfs2(will,will);
}
}
void work(){
int x,y;
while(m--){
x=read();y=read();
ST::work_add(x,y);
}
printf("%d\n",ST::query(1,n,1));
}
void init(){
int x,y;
n=read();m=read();
for(int i=1;i<n;i++){
x=read();y=read();
add(x,y);
}
deep[1]=1;
dfs1(1);
dfs2(1,1);
ST::buildtree(1,n,1);
}
int main(){
init();
work();
return 0;
}
总耗时3244ms。
解法二:
这题可以不用在线做,那么我们就有一个很NOIP的算法——树上差分!
若操作的节点是u,v,那么只要在差分数组num[]中这样:
int lca=LCA(u,v);
num[u]++;num[v]++;
num[lca]--;num[fa[lca]]--;
最后再用一个dfs求出和:
void get_sum(int rt){
sum[rt]=num[rt];
for(int i=head[rt];i;i=a[i].next){
int will=a[i].to;
if(will==fa[rt])continue;
get_sum(will);
sum[rt]+=sum[will];
}
ans=max(ans,sum[rt]);
}
这样,sum[]数组中就是权值了。
那个LCA我不管你怎么求,反正什么倍增啊,树剖啊什么乱七八糟的玩意搞出来就行了。。。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 50010
using namespace std;
int n,m,c=1,ans=0;
int num[MAXN],sum[MAXN],head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],top[MAXN];
struct node{
int next,to;
}a[MAXN<<1];
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
inline void add(int x,int y){
a[c].to=y;a[c].next=head[x];head[x]=c++;
a[c].to=x;a[c].next=head[y];head[y]=c++;
}
void dfs1(int rt){
son[rt]=0;size[rt]=1;
for(int i=head[rt];i;i=a[i].next){
int will=a[i].to;
if(!deep[will]){
deep[will]=deep[rt]+1;
fa[will]=rt;
dfs1(will);
size[rt]+=size[will];
if(size[son[rt]]<size[will])son[rt]=will;
}
}
}
void dfs2(int rt,int f){
top[rt]=f;
if(son[rt])dfs2(son[rt],f);
for(int i=head[rt];i;i=a[i].next){
int will=a[i].to;
if(will!=fa[rt]&&will!=son[rt])
dfs2(will,will);
}
}
int LCA(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
x=fa[top[x]];
}
if(deep[x]>deep[y])swap(x,y);
return x;
}
void get_sum(int rt){
sum[rt]=num[rt];
for(int i=head[rt];i;i=a[i].next){
int will=a[i].to;
if(will==fa[rt])continue;
get_sum(will);
sum[rt]+=sum[will];
}
ans=max(ans,sum[rt]);
}
void work(){
int x,y;
while(m--){
x=read();y=read();
int lca=LCA(x,y);
num[x]++;num[y]++;num[lca]--;num[fa[lca]]--;
}
get_sum(1);
printf("%d\n",ans);
}
void init(){
int x,y;
n=read();m=read();
for(int i=1;i<n;i++){
x=read();y=read();
add(x,y);
}
deep[1]=1;
dfs1(1);
dfs2(1,1);
}
int main(){
init();
work();
return 0;
}
总耗时:780ms
由此,我们可以看到,树上差分的速度几乎是树剖的4倍!
在NOIP这种严重卡常的比赛中,不到万不得已,不要用两个log的算法。。。
BZOJ4390: [Usaco2015 dec]Max Flow的更多相关文章
- bzoj4390: [Usaco2015 dec]Max Flow(LCA+树上差分)
题目大意:给出一棵树,n(n<=5w)个节点,k(k<=10w)次修改,每次给定s和t,把s到t的路径上的点权+1,问k次操作后最大点权. 对于每次修改,给s和t的点权+1,给lca(s, ...
- BZOJ 4390: [Usaco2015 dec]Max Flow
4390: [Usaco2015 dec]Max Flow Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 177 Solved: 113[Submi ...
- [Usaco2015 dec]Max Flow 树上差分
[Usaco2015 dec]Max Flow Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 353 Solved: 236[Submit][Sta ...
- 【bzoj4390】[Usaco2015 dec]Max Flow LCA
题目描述 Farmer John has installed a new system of N−1 pipes to transport milk between the N stalls in h ...
- [Usaco2015 dec]Max Flow
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 204 Solved: 129[Submit][Status][Discuss] Descriptio ...
- 【BZOJ4391】[Usaco2015 dec]High Card Low Card(贪心)
[BZOJ4391][Usaco2015 dec]High Card Low Card(贪心) 题面 BZOJ 题解 预处理前缀后缀的结果,中间找个地方合并就好了. #include<iostr ...
- bzoj4393: [Usaco2015 Dec]Fruit Feast
题意: T,A,B.T是上限.A和B可以随意吃但是不能超过T.有一次将吃的东西/2的机会.然后可以继续吃,不能超过T.问最多可以吃多少. =>我们先处理不能/2可以吃到哪些.然后弄个双指针扫一扫 ...
- USACO Max Flow
洛谷 P3128 [USACO15DEC]最大流Max Flow 洛谷传送门 JDOJ 3027: USACO 2015 Dec Platinum 1.Max Flow JDOJ传送门 Descrip ...
- 洛谷P3128 [USACO15DEC]最大流Max Flow [树链剖分]
题目描述 Farmer John has installed a new system of pipes to transport milk between the stalls in his b ...
随机推荐
- 【转】【Stackoverflow好问题】去掉烦人的“!=null"(判空语句)
[Stackoverflow好问题]去掉烦人的“!=null"(判空语句) 问题 为了避免空指针调用,我们经常会看到这样的语句 ...if (someobject != null) { ...
- 转:Maven项目中获取classpath和资源文件的路径
假设资源文件放在maven工程的 src/main/resources 资源文件夹下,源码文件放在 src/main/java/下, 那么java文件夹和resources文件夹在运行时就是class ...
- codeigniter视图
怎么加载视图? 例如我们有一个视图在 application/views/welcome.php public function index() { $this->load->view(' ...
- SQLServer出现不允许保存更改的问题解决
如图所示: 解决方法: [工具]->[选项]
- C++ 11中几个我比较喜欢的语法(二)
之前在文章C++ 11中几个我比较喜欢的语法中介绍了几个我比较喜欢的C++语法,其中有些语法由于VC 11还不支持,无法跨平台,所以没有介绍.前几天VS 2013 Preview发布后,对C++ 11 ...
- mongodb培训
写在前面 公司组织的技术培训,虽然刚接触mongodb没多久,算是入门吧,就组织一次mongodb的入门ppt培训.包括nosql的简单介绍,以及mongodb的一些优缺点,最后包括mongodb的一 ...
- mysql之select,insert,delete,update
写在前面 上篇文章学习了创建数据库和数据表,这篇文章将学习对数据表的增删改查操作. 系列文章 mysql之创建数据库,创建数据表 一个例子 上篇文章中,创建了数据库和数据表,数据表中还没有数据,这里我 ...
- 【温故知新】——CSS黑魔法小技巧可以少些不必要的js
前言:这篇文章是转载[前端开发博客]的一篇技术文章,并非本人所写.只是个人觉得很实用,所以分享给大家.原文链接:github.com 1.利用 CSS 的 content 属性 attr 抓取资料需求 ...
- Tomcat的Manager显示403 Access Denied
管理tomcat的时候遇到了以下问题: 1.刚开始需要用户名密码,不知道用户名和密码是什么,但是输入什么都不正确. 解决办法: 自己在tomcat-users.xml中按格式添加用户 conf文件夹里 ...
- remove-duplicates-from-sorted-list I&II——去除链表中重复项
I.Given a sorted linked list, delete all duplicates such that each element appear only once. For exa ...