树上差分入门例题

树上差分入门例题

树上差分入门


P3128 [USACO15DEC]Max Flow P

洛谷P3128


提示:以下是本篇文章正文内容,下面案例可供参考

一、题目大意

从s到t每一个地方都会增加一个压力,我们需要找出最大的压力。表达能力是什么,不存在的

二、思路

看了洛谷的题解才知道要用到树上差分。
什么是树上差分?
树上差分是什么?
怎么用
我个人的理解:
树上差分的应用:
1.找被所有路径共同覆盖的边。
sum[s]++,sum[t]++,sum[LCA(s,t)]-=2
2.将路径上的所有点权值加一,求最后点的权值。(这道题)
sum[u]++,sum[v]++,sum[LCA(u,v)]–,sum[f[LCA(u,v)][0]]–

代码:

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#define ll long long 
using namespace std;
const int maxn=1e5+10;
int f[maxn][30];
int n,k,s,t;
int head[maxn],cnt; 
struct edge
{
    int next,to;
}e[maxn<<1];
int sum[maxn],ans;
int dep[maxn];
void add (int u,int v)
{
    e[++cnt].next=head[u];
    e[cnt].to=v;
    head[u]=cnt; 
    return ;
}
void dfs(int u,int fa)
{
    dep[u]=dep[fa]+1;
    f[u][0]=fa;
    for (int i=1;(1<<i)<=dep[u];i++)
    {
        f[u][i]=f[f[u][i-1]][i-1];
    }
    for (int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if (v==fa) continue; 
        dfs(v,u);
    }
    return ;
}
int lca(int u,int v)//这里是一个lca的模板
{
    if (dep[u]<dep[v]) swap(u,v);
    for (int i=20;i>=0;i--)
    {
        if ((1<<i)<=dep[u]-dep[v])
        {
             u=f[u][i];
        }
    }
    if (u==v) return u;
    for (int i=20;i>=0;i--)
    {
        if (f[u][i]!=f[v][i])
        {
            u=f[u][i];
            v=f[v][i];
        }
    }
    return f[u][0];//u的父节点
}
void getmax(int u,int fa)//找出最大的
{
    for (int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if (v==fa) continue ;
        getmax(v,u);
        sum[u]+=sum[v];
    }
    ans=max(ans,sum[u]);
    return ;
}
int main ()
{
    scanf ("%d%d",&n,&k);
    for (int i=1;i<n;i++)
    {
        int u,v;
        scanf ("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    dfs(1,0);
    while (k--)
    {
        scanf ("%d%d",&s,&t);
        int fa=lca(s,t);//第二种应用
        sum[s]++;
        sum[t]++;
        sum[fa]--;
        sum[f[fa][0]]--;
    }
    getmax(1,0);
    printf ("%d\n",ans);
    system("pause");
    return 0;
}

总结

这是我做的第一道树上差分的题,写这个的时候还不记得lca了,看来这些还是要多写写,背一背。
欢迎大家指教!

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值