树链剖分:洛谷P3128 最大流Max Flow

题目连接:最大流Max Flow
题解:

这道题可以用树上点差分解决,也可以用树链剖分写,上一篇博客使用树上点差分写的,这次因为我刚学树剖,所以用树剖将这到题写了

树剖的写法:第一遍dfs()将重儿子,每个点的父亲,每个点的深度标记出来,第二遍dfs()按照重儿子的顺序进行有优先dfs()
得到当前的dfs序,此时树已经被剖分好了,然后我们就写一个线段树求区间最大值,因为是区间修改,所以需要用上懒人标记,如何修改树上任意一条链的权值,其实很简单,因为我们是按重儿子进行剖分的,所以重儿子上的dfs序一定是连续的,所以我们只需要将两个节点的头一致即可直接修改

注意:

我们先修改深度大的,这样就不会产生多修改的情况了,每次比较当前节点所在链的头的深度,修改深度大的节点和它的头所在的链即可

while(top[x]!=top[y)
{
  if(deep[top[x]]<deep[top[y]])
  {
  
  }
}

AC代码:

#include<bits/stdc++.h>
using namespace std;
//p3128 树链剖分
const int maxn=1e5+5;
int n,q,cnt1,cnt2;
int head[maxn],sizx[maxn],pre[maxn],deep[maxn],son[maxn];
int dfn[maxn],topx[maxn];
struct node
{
    int to,nex;
} edge[maxn*2];
void add(int u,int v)
{
    edge[cnt1].to=v;
    edge[cnt1].nex=head[u];
    head[u]=cnt1++;
}
void dfs1(int u,int fa)
{
    deep[u]=deep[fa]+1;
    pre[u]=fa;
    sizx[u]=1;
    int maxson=-1;
    for(int i=head[u]; ~i; i=edge[i].nex)
    {
        int v=edge[i].to;
        if(v!=fa)
        {
            dfs1(v,u);
            sizx[u]+=sizx[v];
            if(sizx[v]>maxson)
            {
                maxson=sizx[v];
                son[u]=v;
            }
        }
    }
}
void dfs2(int u,int top)
{
    dfn[u]=++cnt2;
    topx[u]=top;
    if(!son[u])
    {
        return ;
    }
    dfs2(son[u],top);
    for(int i=head[u]; ~i; i=edge[i].nex)
    {
        int v=edge[i].to;
        if(v==son[u]||v==pre[u])
            continue;
        dfs2(v,v);
    }
}
struct yzj
{
    int l,r,maxx,lazy;
} tr[maxn*4];
void pushup(int k)
{
    tr[k].maxx=max(tr[k<<1].maxx,tr[k<<1|1].maxx);
}
void pushdown(int k)
{
        tr[k<<1].lazy+=tr[k].lazy;
        tr[k<<1|1].lazy+=tr[k].lazy;
        tr[k<<1].maxx+=tr[k].lazy;
        tr[k<<1|1].maxx+=tr[k].lazy;
        tr[k].lazy=0;
}
void build(int k,int l,int r)
{
    tr[k].l=l,tr[k].r=r,tr[k].lazy=0;
    if(l==r)
    {
        tr[k].maxx=0;
        return ;
    }
    int mid=l+r>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    pushup(k);
}
void modify(int k,int l,int r,int w)
{
    if(tr[k].l>=l&&tr[k].r<=r)
    {
        tr[k].maxx+=w;
        tr[k].lazy+=w;
        return;
    }
    pushdown(k);
    int mid=tr[k].l+tr[k].r>>1;
    if(mid>=r)
    {
        modify(k<<1,l,r,w);
    }
    else if(mid<l)
    {
        modify(k<<1|1,l,r,w);
    }
    else
    {
        modify(k<<1,l,mid,w);
        modify(k<<1|1,mid+1,r,w);
    }
    pushup(k);
}
int qmaxson(int k,int l,int r)
{
    if(tr[k].l>=l&&tr[k].r<=r)
    {
        return tr[k].maxx;
    }
    pushdown(k);
    int mid=tr[k].l+tr[k].r>>1;
    if(mid>=r)
    {
        return qmaxson(k<<1,l,r);
    }
    else if(mid<l)
    {
        return qmaxson(k<<1|1,l,r);
    }
    else
    {
        return max(qmaxson(k<<1,l,mid),qmaxson(k<<1|1,mid+1,r));
    }
}
void modify_son(int x,int y,int w)
{
    //cout<<"8***"<<endl;
    while(topx[x]!=topx[y])
    {
        //printf("**\n");
        if(deep[topx[x]]<deep[topx[y]])
            swap(x,y);
        modify(1,dfn[topx[x]],dfn[x],w);
        x=pre[topx[x]];
    }
    if(deep[x]>deep[y])
        swap(x,y);
    //cout<<"8***"<<endl;
    modify(1,dfn[x],dfn[y],w);

}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d %d",&n,&q);
    int u,v;
    for(int i=1; i<n; i++)
    {
        scanf("%d %d",&u,&v);
        add(u,v);
        add(v,u);
    }
    dfs1(1,0);
    dfs2(1,1);

    build(1,1,n);
    while(q--)
    {
        scanf("%d %d",&u,&v);
        modify_son(u,v,1);
    }
    printf("%d\n",qmaxson(1,1,n));

}
发布了221 篇原创文章 · 获赞 16 · 访问量 9746

猜你喜欢

转载自blog.csdn.net/yangzijiangac/article/details/104106459