洛谷 P3128 [USACO15DEC] Max Flow P

news2024/12/22 20:28:06

题目链接:P3128 [USACO15DEC] Max Flow P - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)


前置知识,LCA模板

洛谷 P3379 【模板】最近公共祖先(LCA)-CSDN博客

读题注意

从隔间s运输到隔间t,和从隔间t运输到隔间s,都没区别,因为加的压力是一样的,所以这是一个无向图。

并且只有N个节点和N-1条边,所以是一棵树。

分析

如果每次都去遍历[s,t]这个区间去给每个节点都加上1,那么复杂度肯定会T飞出去,因为是区间修改考虑用差分维护,但是这个是树,改变思路可以将节点s压力+1节点t压力+1lca(s,t)压力-2。

发现直接对lca减二并不符合运输情况,考虑递归回溯性质改成lca(s,t)压力-1lca(s,t)父节点压力-1

这样一边回溯一边累计答案就可以了。

AC代码(倍增求LCA+树上差分)

#include <bits/stdc++.h>
using namespace std;
const int N=5e4+5;

int n,k,p[N],ans=INT_MIN,d[N];
int f[N][20],lg[N];
vector<int>e[N];
bitset<N>vis;
inline int read(){
    int x=0;char c=getchar();
    while(c<48 or c>57)c=getchar();
    while(c>=48 and c<=57)x=(x<<3)+(x<<1)+(c xor 48),c=getchar();
    return x;
}
int lca(int x,int y){
    if(d[x]<d[y])swap(x,y);
    while(d[x]>d[y])x=f[x][lg[d[x]-d[y]]-1];
    if(x==y)return x;
    for(int i=lg[d[x]];i>=0;--i)
        if(f[x][i]!=f[y][i]){
            x=f[x][i];
            y=f[y][i];
        }
    return f[x][0];
}
void dfs(int now,int fa){
    if(vis[now])return;
    vis[now]=true;
    d[now]=d[fa]+1;
    f[now][0]=fa;
    for(int i=1;i<=lg[d[now]];++i)
        f[now][i]=f[f[now][i-1]][i-1];
    for(auto i:e[now])dfs(i,now);
}
void dfs_ans(int now){
    if(vis[now])return;
    vis[now]=true;
    for(auto i:e[now]){
        if(!vis[i]){//一定要加这一句,不然下面p[now]会累计父节点的值
            dfs_ans(i);
            p[now]+=p[i];
        }
    }
    ans=max(ans,p[now]);
}
int main(){
    n=read(),k=read();
    for(int i=1,x,y;i<=n-1;++i){
        x=read(),y=read();
        e[x].push_back(y);
        e[y].push_back(x);
    }

    for(int i=1;i<=n;++i){
        lg[i]=log(i)/log(2)+1;
    }
    dfs(1,1);
    for(int i=1,s,t;i<=k;++i){
        s=read(),t=read();
        int fa=lca(s,t);
        p[s]++,p[t]++,p[fa]--,p[f[fa][0]]--;
    }

    vis.reset();
    dfs_ans(1);
    cout<<ans<<endl;
    return 0;
}

这里面有个坑,用子节点往父节点传递信息的时候,如果是STL开的邻接表一定一定要记得在循环里面加一下父节点的判断,不然debug找两年   :(

包括传递子节点数量这种树上dp也一样。

既然倍增LCA能过,那么不得不试一下用线段树维护欧拉序求LCA了

查询都是log级别,只是线段树的常数会大一点,代码会多一点。

AC代码(线段树维护欧拉序+树上差分)

#include <bits/stdc++.h>
using namespace std;
const int N=5e4+5;

int n,k,p[N],res,f[N],idx[N<<1],st[N<<3],oula[N<<1],oulan,d[N];
vector<int>e[N];
bitset<N>vis;
inline int read(){
    int x=0;char c=getchar();
    while(c<48 or c>57)c=getchar();
    while(c>=48 and c<=57)x=(x<<3)+(x<<1)+(c xor 48),c=getchar();
    return x;
}
void dfs(int x){
    if(vis[x])return;
    vis[x]=true;
    oula[++oulan]=x;
    if(!idx[x])idx[x]=oulan;
    for(auto i:e[x]){
        if(!vis[i]){//用STL写的千万别忘了加这个,不然无向图会累计父节点
            f[i]=x;//最好所有dfs都加这个判断。
            d[i]=d[x]+1;
            dfs(i);
            oula[++oulan]=x;
            if(!idx[x])idx[x]=oulan;
        }
    }
}
void build(int l,int r,int i){
    if(l==r){
        st[i]=oula[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
    st[i]=d[st[i<<1]]<d[st[i<<1|1]]?st[i<<1]:st[i<<1|1];
}
int lca(int l,int r,int i,int x,int y){
    int ans=0;
    if(l>=x and r<=y)return st[i];
    int mid=(l+r)>>1;
    if(x<=mid){
        int t=lca(l,mid,i<<1,x,y);
        if(d[t]<d[ans])ans=t;
    }
    if(y>mid){
        int t=lca(mid+1,r,i<<1|1,x,y);
        if(d[t]<d[ans])ans=t;
    }
    return ans;
}
void dfs_res(int x){
    if(vis[x])return;
    vis[x]=true;
    for(auto i:e[x]){
        if(!vis[i]){
            dfs_res(i);
            p[x]+=p[i];
        }
    }
    res=max(p[x],res);
}

int main(){
    n=read(),k=read();
    for(int i=1,x,y;i<=n-1;++i){
        x=read(),y=read();
        e[x].push_back(y);
        e[y].push_back(x);
    }

    dfs(1);
    build(1,oulan,1);
    d[0]=INT_MAX;

    for(int i=1,s,t;i<=k;++i){
        s=read(),t=read();
        int l=idx[s],r=idx[t],LCA;
        if(l>r)swap(l,r);
        LCA=lca(1,oulan,1,l,r);
        p[s]++,p[t]++,p[LCA]--,p[f[LCA]]--;
    }

    vis.reset();
    dfs_res(1);
    cout<<res<<endl;
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1218226.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HarmonyOS 实战项目

引言 本章将介绍如何在 HarmonyOS 上进行实际项目开发。我们将从项目需求分析开始&#xff0c;逐步完成项目的设计、开发、测试和上线过程。 目录 项目需求分析项目设计项目开发项目测试项目上线总结 1. 项目需求分析 项目需求分析是项目开发的关键阶段之一&#xff0c;它…

论文阅读——RetNet

transformer的问题&#xff1a;计算量大&#xff0c;占用内存大&#xff0c;不好部署。 所以大家在找能解决办法&#xff0c;既能和transformer表现一样好&#xff0c;又能在推理阶段计算复杂度很低。 这些方法大概分类三类&#xff1a;一是代替transformer非线性注意力机制的…

【左程云算法全讲11】贪心算法 并查集

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招面试的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于左程云算法课程进行的&#xff0c;每个知识点的修正和深入主要参考…

text/xml和application/xml

困惑 在http消息中&#xff0c;同样是传送xml信息&#xff0c;有的时候看到Content-Type的值是text/xml&#xff0c;有的时候值是application/xml&#xff0c;感到困惑。 例如&#xff0c;用Postman发送http消息给Tomcat中的基于JAX-WS的 web服务&#xff1a; 请求中传送了xm…

快速搭建本地的chatgpt

快速搭建本地的chatgpt 参考&#xff1a;一篇文章教你使用Docker本地化部署Chatgpt&#xff08;非api&#xff0c;速度非常快&#xff01;&#xff01;&#xff01;&#xff09;及裸连GPT的方式&#xff08;告别镜像GPT&#xff09;-CSDN博客 前提是linux下 已安装docker 命…

系列五、JVM的内存结构【PC寄存器】

一、位置 CPU中 二、作用 每个线程都有一个程序计数器&#xff0c;是线程私有的&#xff0c;所谓PC寄存器其实就是一个指针&#xff0c;指向方法区中的方法字节码&#xff08;用来存储指向下一条指令的地址&#xff0c;也即将要执行的指令代码&#xff09;&#xff0c;由执行引…

反向运算放大器

在学习模拟电路的时候&#xff0c;学习到运算放大器&#xff0c;但实际印象并不深刻&#xff0c;在此进行二次知识整理&#xff0c;以加深深度&#xff0c;下面是我个人对该器件的理解&#xff0c;其他知识暂时不深究&#xff0c;只说一下怎么用。 1、反向运算放大器干什么的&…

Python集成学习和随机森林算法

大家好&#xff0c;机器学习模型已经成为多个行业决策过程中的重要组成部分&#xff0c;然而在处理嘈杂或多样化的数据集时&#xff0c;它们往往会遇到困难&#xff0c;这就是集成学习&#xff08;Ensemble Learning&#xff09;发挥作用的地方。 本文将揭示集成学习的奥秘&am…

Docker(镜像、容器、仓库)工具安装使用命令行选项及构建、共享和运行容器化应用程序

文章目录 前言&#x1f31f;一、Docker工具安装&#x1f31f;二、Docker命令行选项&#x1f30f;2.1.docker run命令选项&#xff1a;&#x1f30f;2.2.docker build命令选项&#xff1a;&#x1f30f;2.3.docker images命令选项&#xff1a;&#x1f30f;2.4.docker ps命令选项…

CTF-PWN-堆-【前置知识】

CTF-PWN-堆 堆申请堆块main_areanabrk&sbrk函数mallocfreefree后top chunk 堆 由malloc alloc realloc 函数分配 chunk的前指的是地址低的&#xff0c;chunk的高指的是地址高的 申请堆块 ptmalloc2堆管理器&#xff1a; 通俗的讲就是相当于一个”中间商”&#xff0c;在…

实用篇-ES-RestClient查询文档

一、快速入门 上面的查询文档都是依赖kibana&#xff0c;在浏览器页面使用DSL语句去查询es&#xff0c;如何用java去查询es里面的文档(数据)呢 我们通过match_all查询来演示基本的API&#xff0c;注意下面演示的是 match_all查询&#xff0c;也叫基础查询 首先保证你已经做好了…

Linux_系统信息_uname查看内核版本、内核建立时间、处理器类型、顺便得到操作系统位数等

1、uname --help 使用uname --help查看uname命令的帮助信息 2、uname -a 通过上面的help就知道-a选项显示全部内容时的含义了。 内核名是Linux主机名是lubancat&#xff0c;如果想看主机名可以使用命令hostname&#xff1b;内核版本是Linux 4.19.232&#xff0c;建立时间为2…

解锁编程潜能:探索亚马逊CodeWhisperer,打造编程世界的声音引导者

文章目录 前言一、什么是 Amazon CodeWhisperer&#xff1f;二、如何使用CodeWhisperer&#xff1f;安装CodeWhisperer插件配置CodeWhisperer生成注释和文档 总结 前言 随着CHATGPT的一声巨响&#xff0c;大语言模型已经成为了一个备受瞩目的创新应用。亚马逊云科技作为全球领…

V10 桌面版、服务器版系统加固

V10 桌面版、服务器版系统加固 一、 文档说明 本文档中涉及的加固方法主要包括&#xff1a;密码策略配置、防火墙规 则配置、禁用高风险服务等。 二、 V10 桌面版系统加固 2.1 密码策略配置 密码策略包括密码老化控制策略和密码复杂度策略。密码老化 控制策略需要配置/etc…

Power Automate-当收到HTTP请求时触发流程

选择创建自动化云端流&#xff0c;点跳过 第一个操作搜索HTTP&#xff0c;点击当收到HTTP请求时 点击使用示例有效负载生成架构 写入JSON&#xff0c;点击完成 正文JSON架构就自动生成了&#xff0c;再点击左下角的显示高级选项 Method根据需求选择 可以选择JSON中的参数赋值给…

网络安全(黑客技术)—高效自学

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0c;但是连方向都没搞清楚就开始学习…

【ARM Trace32(劳特巴赫) 使用介绍 2.1 -- TRACE32 Practice 脚本 cmm 脚本学习】

请阅读【ARM Coresight SoC-400/SoC-600 专栏导读】 上篇文章【ARM Trace32(劳特巴赫) 使用介绍 2 - Veloce 环境中使用trace32 连接 Cortex-M33】 下篇文章【ARM Trace32(劳特巴赫) 使用介绍 2.2 – TRACE32 进阶命令之 DIAG 弹框命令】 文章目录 1. TRACE32 Practice 语法1.…

【转载】快速搭建OpenGL环境!!!Windows10 + Visual Studio 2019 搭建OpenGL环境

目录 具体链接&#xff1a; 【转自】 完成后效果如下&#xff1a; 一开始的爆红&#xff1a; 下载安装后&#xff1a; 运行成功&#xff1a; 具体链接&#xff1a; 萌新向&#xff01;&#xff01;&#xff01;Windows10 Visual Studio 2019 搭建OpenGL环境&#xff08;…

StringBuffer和StringBuilder的区别与联系

文章目录 区别一览StringBuffer如何实现多线程同步关键字&#xff08;Synchronized&#xff09;性能考虑使用场景 当不使用多线程的情况下&#xff0c;是否StringBuffer和StringBuilder的性能一样&#xff1f;性能差异原因实践中的选择结论 区别一览 StringBuffer 和 StringBu…