USACO15DEC最大流MaxFlow

本文介绍了一种使用树剖和线段树解决道路压力问题的方法,通过将道路对路径的压力转化为对路径上点的权值加1,并最终求解整个树中的最大值,巧妙地解决了问题。

传送门

这是个假的最大流,其实是一个用树剖+线段树就能解决的事情

题目中的道路会对路径上的造成压力,最后询问最大的压力

其实就等价于对每条路径上的点加上 1 的权值,并且最后询问整个树中的最大值

然后树剖+最大值线段树裸题,完事,莫得别的问题了.

Code:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <vector>
#define ls ( rt << 1 )
#define rs ( rt << 1 | 1 )
#define mid ( ( l + r ) >> 1 )
#define pushup(rt) t[rt].data = max ( t[ls].data , t[rs].data )

using std::vector ;
using std::max ;

const int N = 1e5 + 5 ;

struct seg {
    int left , right , data , tag ;
    inline int size () { return right - left + 1 ; }
}t[(N<<2)] ;

vector < int > G[N] ;
int n , k , val[N] , son[N] , idx[N] , ans ;
int tot , deep[N] , f[N] , siz[N] , top[N] ;

inline void dfs ( int cur , int anc , int dep ) {
    f[cur] = anc ; deep[cur] = dep ; siz[cur] = 1 ;
    int maxson = - 1 ; for ( int k : G[cur] ) {
        if ( k == anc ) continue ;
        dfs ( k , cur , dep + 1 ) ; siz[cur] += siz[k] ;
        if ( siz[k] > maxson ) maxson = siz[k] , son[cur] = k ;
    }
    return ;
}

inline void _dfs ( int cur , int topf ) {
    top[cur] = topf ; idx[cur] = ++ tot ; val[tot] = 0 ;
    if ( ! son[cur] ) return ; _dfs ( son[cur] , topf ) ;
    for ( int k : G[cur] ) {
        if ( k == f[cur] || k == son[cur] ) continue ;
        _dfs ( k , k ) ;
    }
    return ;
}

inline void build ( int rt , int l , int r ) {
    t[rt].left = l ; t[rt].right = r ; t[rt].tag = 0 ;
    if ( l == r ) { t[rt].data = val[l] ; return ; }
    build ( ls , l , mid ) ; build ( rs , mid + 1 , r ) ;
    pushup ( rt ) ; return ;
}

inline void pushdown ( int rt ) {
    t[ls].tag += t[rt].tag ; t[rs].tag += t[rt].tag ;
    t[ls].data += t[rt].tag ; t[rs].data += t[rt].tag ;
    t[rt].tag = 0 ; return ;
}

inline void update ( int rt , int ll , int rr , int key ) {
    int l = t[rt].left , r = t[rt].right ;
    if ( ll <= l && r <= rr ) {
        t[rt].tag += key ;
        t[rt].data += key ;
        return ;
    }
    if ( t[rt].tag != 0 ) pushdown ( rt ) ;
    if ( ll <= mid ) update ( ls , ll , rr , key ) ;
    if ( rr > mid ) update ( rs , ll , rr , key ) ;
    pushup ( rt ) ; return ;
}

inline void query ( int rt , int ll , int rr ) {
    int l = t[rt].left , r = t[rt].right ;
    if ( ll <= l && r <= rr ) {
        ans = max ( ans , t[rt].data ) ;
        return ;
    }
    if ( t[rt].tag != 0 ) pushdown ( rt ) ;
    if ( ll <= mid ) query ( ls , ll , rr ) ;
    if ( rr > mid ) query ( rs , ll , rr ) ;
    return ;
}

inline void uprange (int x , int y , int key) {
    while ( top[x] != top[y] ) {
        if ( deep[top[x]] < deep[top[y]] ) std::swap ( x , y ) ;
        update ( 1 , idx[top[x]] , idx[x] , key ) ; x = f[top[x]] ;
    }
    if ( deep[x] > deep[y] ) std::swap ( x , y ) ;
    update ( 1 , idx[x] , idx[y] , key ) ; return ;
}

int main () {
    scanf ("%d%d" , & n , & k ) ;
    for (int i = 1 ; i < n ; ++ i) {
        register int u , v ;
        scanf ("%d%d" , & u , & v ) ;
        G[u].push_back ( v ) ;
        G[v].push_back ( u ) ;
    }
    dfs ( 1 , 0 , 1 ) ; _dfs ( 1 , 1 ) ; build ( 1 , 1 , tot ) ;
    while ( k -- ) {
        register int u , v ;
        scanf ("%d%d" , & u , & v ) ;
        uprange ( u , v , 1 ) ;
    }
    ans = - 1 ; query ( 1 , idx[1] , idx[1] + siz[1] - 1 ) ;
    printf ("%d\n" , ans ) ; system ("pause") ; return 0 ;
}

转载于:https://www.cnblogs.com/Equinox-Flower/p/10785248.html

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值