[JZOJ1904] [2010] Rescue Team of the topic and the home of the Protoss

topic

Subject to the effect

Give you a tree network, each edge flows son from his father. Root origin, leaf node flow to the sink capacity is infinite.
We can give some edge to expand the capacity, up to a total of expanding \ (m \) capacity. Each side has a capacity limit.
Seeking to expand the maximum capacity of the largest stream.


Reflections on History

Vaguely guessed positive solutions have to do with the chain tree split, but did not play, there is no time to play.
DP violence can only be moisture.
Set \ (h_ {i, j} \) of \ (I \) is the father \ (I \) of the maximum flow, the expanded \ (J \) times the capacity. \ (g_ {i, j} \) of \ (I \) max flow subtree to expand the \ (J \) times the capacity. The former takes a minimum value obtained by the capacity of the latter and the edge.
Transfer equation is clear.
In this way the water \ (70 \) points, more than expected \ (20 \) points.


Correct

There is a cost flow approach: for each different father to son even cost two sides. Expand once the equivalent of a little more cost.
Running Minimum Cost Maximum, minimum each way to election expenses augmented, it costs no more than \ (m \) maximum flow is the answer when.
This approach is \ (O (n ^ 2) \) a. Because after each side augmented at least there will be a full flow, the equivalent deleted this edge.
Commentary desired title score \ (100 \) ...... ...... But I really served anyone really such a fight on over ......

Correct answer is to optimize the cost flow problem ...... commentary by using the properties tree \ (LCT \) , I see people playing solution to a problem of logistics is too. This is obviously the amount of code for such a long title, also playing \ (LCT \) ?
Next we simulate cost flow process:

  1. Find a minimal cost from the root node to the leaf nodes of the path.
  2. This obtains the maximum flow path \ (F \) (i.e. the capacity of the smallest side of the path).
  3. Statistics into the answers.
  4. Capacity on all sides of the path are subtracted \ (f \) .
  5. The full flow on the modified path while looking out (i.e. capacity \ (0 \) side). Category talk: if the cost is \ (0 \) , then modify it costs \ (1 \) , and modify its capacity; if the cost is \ (1 \) , mark this edge can not go through (that is, All descendants can not reach).

Of course, remember to look at the special judge is about to be greater than \ (m \) situations.

This thing with the tree split and chain segment tree to maintain. Tree line maintenance information: minimum capacity \ (f \) and his son's number \ (numf \) (the path of a strip from top to bottom edge of the smallest capacity), as well as the minimum cost \ (w \ ) and the leaf node number \ (numw \) (the fee for the root node to the leaf node path and fees).
Operation \ (1 \) when the minimum is to ask \ (W \) .
Operation \ (2 \) , when the current node is the root path to the smallest \ (F \) .
Operation \ (4 \) all edges interval when the current node is the root path to the Save \ (F \) .
Operation \ (5 \) when the cost is all leaf nodes of the current node can be added to the interval \ (1 \) or infinite.
These operations is a ......


Code

Long ...... Fortunately, the tree split and chain segment tree good fight ......

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <cassert>
#define N 10010
#define INF 1000000000
int n,m;
struct EDGE{
    int to;
    EDGE *las;
} e[N];
int ne;
EDGE *last[N];
bool leaf[N];
int a[N],b[N];
int fa[N],siz[N],hs[N];
int top[N],dfn[N],nowdfn,to_num[N];
int noww[N];
void dfs1(int x){
    siz[x]=1;
    for (EDGE *ei=last[x];ei;ei=ei->las){
        fa[ei->to]=x;
        dfs1(ei->to);
        siz[x]+=siz[ei->to];
        if (siz[ei->to]>siz[hs[x]])
            hs[x]=ei->to;
    }
    if (siz[x]==1)
        leaf[x]=1;
}
void dfs2(int x,int t){
    top[x]=t;
    dfn[x]=++nowdfn;
    to_num[nowdfn]=x;
    if (hs[x])
        dfs2(hs[x],t);
    for (EDGE *ei=last[x];ei;ei=ei->las)
        if (ei->to!=hs[x])
            dfs2(ei->to,ei->to);
}
struct Node{
    int f,numf;
    int w,numw;
    int tagf,tagw;
} seg[N*4];
inline void updatef(int k){
    if (seg[k<<1].f<=seg[k<<1|1].f)
        seg[k].f=seg[k<<1].f,seg[k].numf=seg[k<<1].numf;
    else
        seg[k].f=seg[k<<1|1].f,seg[k].numf=seg[k<<1|1].numf;
}
inline void updatew(int k){
    if (seg[k<<1].w<=seg[k<<1|1].w)
        seg[k].w=seg[k<<1].w,seg[k].numw=seg[k<<1].numw;
    else
        seg[k].w=seg[k<<1|1].w,seg[k].numw=seg[k<<1|1].numw;
}
inline void pushdown(int k){
    if (seg[k].tagf){
        seg[k<<1].f+=seg[k].tagf;
        seg[k<<1|1].f+=seg[k].tagf;
        seg[k<<1].tagf+=seg[k].tagf;
        seg[k<<1|1].tagf+=seg[k].tagf;
        seg[k].tagf=0;
    }
    if (seg[k].tagw){
        if (seg[k].tagw>=INF)
            seg[k<<1].w=seg[k<<1|1].w=seg[k<<1].tagw=seg[k<<1|1].tagw=INF;
        else{
            seg[k<<1].w+=seg[k].tagw;
            seg[k<<1|1].w+=seg[k].tagw;
            seg[k<<1].tagw+=seg[k].tagw;
            seg[k<<1|1].tagw+=seg[k].tagw;
            seg[k].tagw=0;
        }
    }
}
void build(int k,int l,int r){
    if (l==r){
        if (leaf[to_num[l]])
            seg[k]={a[to_num[l]],to_num[l],0,to_num[l],0,0};
        else
            seg[k]={a[to_num[l]],to_num[l],INF,0,0,0};
        return;
    }
    int mid=l+r>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    updatef(k),updatew(k);
}
void changef(int k,int l,int r,int st,int en,int c){
    if (st<=l && r<=en){
        seg[k].f+=c;
        seg[k].tagf+=c;
        return;
    }
    pushdown(k);
    int mid=l+r>>1;
    if (st<=mid)
        changef(k<<1,l,mid,st,en,c);
    if (mid<en)
        changef(k<<1|1,mid+1,r,st,en,c);
    updatef(k);
}
void changew(int k,int l,int r,int st,int en,int c){
    if (st<=l && r<=en){
        if (c>=INF)
            seg[k].w=seg[k].tagw=INF;
        else{
            seg[k].w+=c;
            seg[k].tagw+=c;
        }
        return;
    }
    pushdown(k);
    int mid=l+r>>1;
    if (st<=mid)
        changew(k<<1,l,mid,st,en,c);
    if (mid<en)
        changew(k<<1|1,mid+1,r,st,en,c);
    updatew(k);
}
pair<int,int> un(const pair<int,int> &a,const pair<int,int> &b){return a.first<=b.first?a:b;}
pair<int,int> queryf(int k,int l,int r,int st,int en){
    if (st<=l && r<=en)
        return {seg[k].f,seg[k].numf};
    pushdown(k);
    int mid=l+r>>1;
    pair<int,int> res(INF,0);
    if (st<=mid)
        res=un(res,queryf(k<<1,l,mid,st,en));
    if (mid<en)
        res=un(res,queryf(k<<1|1,mid+1,r,st,en));
    return res;
}
int queryw(int k,int l,int r,int x){
    if (l==r)
        return seg[k].tagw;
    pushdown(k);
    int mid=l+r>>1;
    if (x<=mid)
        return queryw(k<<1,l,mid,x);
    return queryw(k<<1|1,mid+1,r,x);
}
inline int flow(int x){
    int res=INT_MAX;
    for (;x;x=fa[top[x]])
        res=min(res,queryf(1,1,n,dfn[top[x]],dfn[x]).first);
    return res;
}
inline void find(int x,int c){
    for (int y=x;y;y=fa[top[y]])
        changef(1,1,n,dfn[top[y]],dfn[y],-c);
    for (;x;x=fa[top[x]]){
        while (x){
            pair<int,int> tmp=queryf(1,1,n,dfn[top[x]],dfn[x]);
            if (tmp.first)
                break;
            if (noww[tmp.second]==0){
                noww[tmp.second]=1;
                changew(1,1,n,dfn[tmp.second],dfn[tmp.second]+siz[tmp.second]-1,1);
                changef(1,1,n,dfn[tmp.second],dfn[tmp.second],b[tmp.second]);
            }
            else{
                changew(1,1,n,dfn[tmp.second],dfn[tmp.second]+siz[tmp.second]-1,INF);
                x=fa[tmp.second];
            }
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    a[1]=INT_MAX;
    for (int i=1;i<=n;++i){
        int u,v;
        scanf("%d%d",&u,&v);
        u++,v++;
        e[ne]={v,last[u]};
        last[u]=e+ne++;
        scanf("%d%d",&a[v],&b[v]);
        b[v]=min(b[v]-a[v],m);
    }
    n++;
    dfs1(1),dfs2(1,1);
    build(1,1,n);
    int ans=0;
    while (1){
        int x=seg[1].numw,cost=seg[1].w;
        if (cost>=INF)
            break;
        int plus=flow(x);
        if (m<cost*plus){
            ans+=m/cost;
            break;
        }
        m-=cost*plus;
        ans+=plus;
        find(x,plus);
    }
    printf("%d\n",ans);
    return 0;
}

to sum up

Sometimes network flow data structure can be maintained ......

Guess you like

Origin www.cnblogs.com/jz-597/p/11329599.html