[Usaco2015 dec]Max Flow

Title Description

Given a tree has N points, weights of 0 to all nodes.

There operation K times, each time two designated points s, t, s to the right of all points on the path are added to a value t.

Please output right after completion of the maximum weight that point the value of K operations.

Input Format

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 ss and t describing the endpoint stalls of a path through which milk is being pumped.

Output Format

An integer specifying the maximum amount of milk pumped through any stall in the barn.


At first glance chain split tree. But it seems that the algorithm does not need to use such violence.

We can use a tree difference. How difference it? For a path s-> t, we can put the right point where s and t + 1, and the point where the right lca -1, then father of the point right at lca -1. Once this is done, we find again and prefix tree, you will find the right point value on the original path are added to the 1, but did not affect other parts of (emotional understand why). The prefix and the biggest place is the answer.

lca with Tarjan request, then the time can be done complexity O (N + M).

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 50001
#define maxm 100001
using namespace std;
 
struct edge{
    int to,next;
    edge(){}
    edge(const int &_to,const int &_next){ to=_to,next=_next; }
}e[maxn<<1];
int head[maxn],k;
 
struct question{
    int to,lca,next; bool flag;
    question(){}
    question(const int &_to,const int &_next,const bool &_flag){ to=_to,next=_next,flag=_flag; }
}q[maxm<<1];
int qhead[maxn],qk;
 
int sum[maxn],fa[maxn],pre[maxn];
bool vis[maxn];
int n,m,ans;
 
inline int read(){
    register int x(0),f(1); register char c(getchar());
    while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
    while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
inline void add(const int &u,const int &v){ e[k]=edge(v,head[u]),head[u]=k++; }
inline void link(const int &u,const int &v,const bool &f){ q[qk]=question(v,qhead[u],f),qhead[u]=qk++; }
 
int get(int x){ return x==fa[x]?x:fa[x]=get(fa[x]); }
void tarjan(int u){
    vis[u]=true,fa[u]=u;
    for(register int i=head[u];~i;i=e[i].next){
        int v=e[i].to;
        if(vis[v]) continue;
        pre[v]=u,tarjan(v),fa[v]=u;
    }
    for(register int i=qhead[u];~i;i=q[i].next){
        int v=q[i].to;
        if(vis[v]&&!q[i].flag){
            q[i].flag=q[i^1].flag=true,q[i].lca=q[i^1].lca=get(v);
            sum[u]++,sum[v]++,sum[get(v)]--,sum[pre[get(v)]]--;
        }
    }
}
 
void dfs_getans(int u){
    for(register int i=head[u];~i;i=e[i].next){
        int v=e[i].to;
        if(v==pre[u]) continue;
        dfs_getans(v);
        sum[u]+=sum[v];
    }
    ans=max(ans,sum[u]);
}
 
int main(){
    memset(head,-1,sizeof head),memset(qhead,-1,sizeof qhead);
    n=read(),m=read();
    for(register int i=1;i<n;i++){
        int u=read(),v=read();
        add(u,v),add(v,u);
    }
    for(register int i=1;i<=m;i++){
        int u=read(),v=read();
        link(u,v,false),link(v,u,false);
    }
 
    tarjan(1);
    dfs_getans(1);
    printf("%d\n",ans);
    return 0;
}

Then put the code section of a tree (most times out):

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 50001
using namespace std;

struct edge{
    int to,next;
    edge(){}
    edge(const int &_to,const int &_next){
        to=_to,next=_next;
    }
}e[maxn<<1];
int head[maxn],k;

struct node{
    int l,r,c,f;
}t[maxn<<2];

inline int read(){
    register int x(0),f(1); register char c(getchar());
    while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
    while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x;
}

int size[maxn],dep[maxn],son[maxn],fa[maxn];
int top[maxn],dfn[maxn],id[maxn],tot;
int n,m;

inline void add(const int &u,const int &v){
    e[k]=edge(v,head[u]);
    head[u]=k++;
}

void dfs_getson(int u){
    size[u]=1;
    for(register int i=head[u];~i;i=e[i].next){
        int v=e[i].to;
        if(v==fa[u]) continue;
        fa[v]=u,dep[v]=dep[u]+1;
        dfs_getson(v);
        size[u]+=size[v];
        if(size[v]>size[son[u]]) son[u]=v;
    }
}

void dfs_rewrite(int u,int tp){
    top[u]=tp,dfn[u]=++tot,id[tot]=u;
    if(son[u]) dfs_rewrite(son[u],tp);
    for(register int i=head[u];~i;i=e[i].next){
        int v=e[i].to;
        if(v!=son[u]&&v!=fa[u]) dfs_rewrite(v,v);
    }
}

void build(int d,int l,int r){
    t[d].l=l,t[d].r=r;
    if(l==r) return;
    int mid=l+r>>1;
    build(d<<1,l,mid),build(d<<1|1,mid+1,r);
}

inline void down(const int &d){
    t[d<<1].c+=t[d].f*(t[d<<1].r-t[d<<1].l+1);
    t[d<<1|1].c+=t[d].f*(t[d<<1|1].r-t[d<<1|1].l+1);
    t[d<<1].f+=t[d].f;
    t[d<<1|1].f+=t[d].f;
    t[d].f=0;
}

void change(int d,const int &l,const int &r){
    if(l<=t[d].l&&t[d].r<=r){ t[d].c+=t[d].r-t[d].r+1,t[d].f++; return; }
    if(t[d].f) down(d);
    int mid=t[d].l+t[d].r>>1;
    if(l<=mid) change(d<<1,l,r);
    if(r>mid) change(d<<1|1,l,r);
    t[d].c=t[d<<1].c+t[d<<1|1].c;
}

int find(int d,const int &x){
    if(t[d].l==t[d].r) return t[d].c;
    if(t[d].f) down(d);
    int mid=t[d].l+t[d].r>>1;
    if(x<=mid) return find(d<<1,x);
    else return find(d<<1|1,x);
}

int main(){
    memset(head,-1,sizeof head);
    n=read(),m=read();
    for(register int i=1;i<n;i++){
        int u=read(),v=read();
        add(u,v),add(v,u);
    }
    dfs_getson(1);
    dfs_rewrite(1,1);
    build(1,1,tot);
    
    for(register int i=1;i<=m;i++){
        int u=read(),v=read();
        while(top[u]!=top[v]){
            if(dep[top[u]]>dep[top[v]]) swap(u,v);
            change(1,dfn[top[v]],dfn[v]);
            v=fa[top[v]];
        }
        if(dep[u]>dep[v]) swap(u,v);
        change(1,dfn[u],dfn[v]);
    }
    
    int ans=0;
    for(int i=1;i<=n;i++) ans=max(ans,find(1,dfn[i]));
    printf("%d\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/akura/p/10945646.html