首页 > 其他分享 >[2022.10.11 模拟赛] 联通块

[2022.10.11 模拟赛] 联通块

时间:2022-10-11 15:55:30浏览次数:44  
标签:11 cnt 联通 int siz mxs MAXN include 2022.10

题意简述

给定一颗树,每个点有点权 \((a_i,b_i)\)。

问满足 \(\sum a_i \le m\) 的连通块的 \(\sum b_i\) 的最大值。

\(n \le 10^3,m \le 10^4\)

分析

有一个显然的 \(\mathcal O(nm^2)\) 的树 dp,瓶颈在于合并背包。

这里有一个 trick: 连通块问题在 dfn 序上 dp 做到单点加入

选了儿子必须选父亲,可以在 dfn 序列上倒序考虑,

记 \(f_{i,j}\) 表示考虑 dfn 序列上后 \(i\) 个点,选出的 \(\sum a=j\) 的 \(\sum b\) 的最大值

  • 选 \(i\) , 那么子树随意, \(f_{i,j} = f_{i+1,j-a_{p_i}}+b_{p_i}\)

  • 不选 \(i\) ,那么子树不能选 , \(f_{i,j}=f_{i+siz_{p_i},j}\)

考虑包含根的连通块,然后删掉根并递归所有子树,可以使用点分治做到 \(\mathcal O(nm \log n)\)

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;

const int MAXN = 1000 , MAXM = 10000 , Inf = 0x3f3f3f3f;
int n , m , a[ MAXN + 5 ] , b[ MAXN + 5 ];
vector< int > Graph[ MAXN + 5 ];

int rt , als , mns , siz[ MAXN + 5 ];
bool del[ MAXN + 5 ];
void dfs1( int u , int fa ) {
    siz[ u ] = 1; int mxs = 0;
    for( int v : Graph[ u ] ) if( v != fa && !del[ v ] ) {
        dfs1( v , u ); siz[ u ] += siz[ v ];
        mxs = max( mxs , siz[ v ] );
    } mxs = max( mxs , als - siz[ u ] );
    if( !rt || mxs < mns ) rt = u , mns = mxs;
}

int cnt , seq[ MAXN + 5 ];
void dfs3( int u , int fa ) {
    seq[ ++ cnt ] = u;
    for( int v : Graph[ u ] ) if( v != fa && !del[ v ] ) dfs3( v , u );
}

int ans , dp[ MAXN + 5 ][ MAXM + 5 ];
void dfs2( int u ) {
    del[ u ] = 1;
    cnt = 0; dfs3( u , 0 );

    dp[ cnt + 1 ][ 0 ] = 0;
    for( int i = cnt ; i >= 1 ; i -- ) {
        for( int j = 0 ; j <= m ; j ++ ) {
            //选 i
            if( j + a[ seq[ i ] ] <= m )
                dp[ i ][ j + a[ seq[ i ] ] ] = max( dp[ i ][ j + a[ seq[ i ] ] ] , dp[ i + 1 ][ j ] + b[ seq[ i ] ] );
            //不选
            dp[ i ][ j ] = max( dp[ i ][ j ] , dp[ i + siz[ seq[ i ] ] ][ j ] );
        }
    }
    for( int i = 1 ; i <= m ; i ++ ) ans = max( ans , dp[ 1 ][ i ] );
    for( int i = 1 ; i <= cnt + 1 ; i ++ ) for( int j = 0 ; j <= m ; j ++ ) dp[ i ][ j ] = -Inf;

    for( int v : Graph[ u ] ) if( !del[ v ] ) {
        rt = 0; als = siz[ v ];
        dfs1( v , u ); dfs1( rt , 0 );
        dfs2( rt );
    }
}
int main( ) {
    scanf("%d %d",&n,&m);
    for( int i = 1 ; i <= n ; i ++ ) scanf("%d %d",&a[ i ],&b[ i ]);
    for( int i = 1 , u , v ; i < n ; i ++ ) {
        scanf("%d %d",&u,&v);
        Graph[ u ].push_back( v );
        Graph[ v ].push_back( u );
    }
    
    rt = 0; als = n;
    dfs1( 1 , 0 ); dfs1( rt , 0 );
    dfs2( rt );

    printf("%d\n", ans );
    return 0;
}

标签:11,cnt,联通,int,siz,mxs,MAXN,include,2022.10
From: https://www.cnblogs.com/chihik/p/16779449.html

相关文章

  • 510约束_外键约束和511和约束_外键约束的级联操作
    外键约束外键约束:foreignkey,让表与表产生关系,从而保证数据的正确性1.在创建表时,可以添加外键语法:CREATETABLE表名(....(值)外键列CONSTRAINT外键名称,FOREIGNKEY(外......
  • 传奇4虚拟机解决DX11提示 独立硬件显卡 虚拟机过检测
    directx11简介DirectX,(DirecteXtension,简称DX)是由微软公司创建的多媒体编程接口。由C++编程语言实现,遵循COM。最新版本为DirectX11,创建在最新的Windows7上。近来好多网友......
  • 10.11
    A.relax小学数学题,前二十五分钟A了,有时间浪费的话就是读题慢。B.Permutation没有构造出来,用一个半小时想题+打了前五十分的表,打表也打得没有技术,完全人工计算。为什么......
  • python之路径 | 11
    写程序的时候,常常需要用到不同得出文件。如果之前保存的比较混乱,找起来真的是一件头疼的事情。如果我们能用python中的路径导入文件,就不会有这种烦扰啦,今天小编就来大家一起......
  • LeetCode 1195. Fizz Buzz Multithreaded
    原题链接在这里:https://leetcode.com/problems/fizz-buzz-multithreaded/题目:Youhavethefourfunctions:printFizz thatprintstheword "fizz" totheconsole......
  • navicat远程连接数据库遇到的问题 11001 unknown error
    今天用navicate连接docker中的MySQL数据库时出现了以下的错误原因:输入主机的IP时在后面多打了一个空格键去除空格之后即可正确连接了......
  • 转载:流动人口3.76亿,他们都去哪儿?2022-10-11
    https://m.thepaper.cn/baijiahao_20247546 流动人口3.76亿,他们都去哪儿?媒体:观察者网 2022-10-1111:13►文第一财经林小昭近年来,我国人口流动有哪些特征?国家......
  • 支持 Java 8/11/17/19 的框架,Solon v1.10.5 版本发布
    Java轻量级应用开发框架。可用来快速开发Java应用项目,主框架仅0.1MB。相对于SpringBoot和SpringCloud的项目:启动快5~10倍。(更快)qps高2~3倍。(更高)......
  • Solution Set -「NOIP Simu.」20221011
    「Unknown」找  给出平面上\(n\)个点,对于每个点,求出它到其他点的欧式距离平方和.  \(n\le2\times10^5\).  Tag:「水题无tag」  画风正常的签到题.\(d......
  • CF1153D
    被*1900薄纱啦,菜死了www假设最终答案不小于\(x\)。如果一个节点上的操作是取\(\min\),那么它的每个儿子节点的值都需要不小于\(x\)。否则它至少有一个儿子节点的值不......