BZOJ2809可合并堆或启发式合并

本文介绍了一种使用multiset替代优先队列解决启发式合并问题的方法,并通过具体实现展示了如何有效地避免内存溢出问题。文章提供了一个完整的C++代码示例,包括自定义的并查集操作和节点更新策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个启发式合并的题目。可以使用可合并堆,但是我觉的不必要,

唯一 的坑点是,优先队列耗费的内存比multiset太多太多,简直可以被淘汰了。用mutiset直接爆内存。所以。相信科学。发现set可以但是priority_queue不可以直接换掉。;。。。

上代码:

#include <algorithm>
#include <assert.h>
#include <complex>
#include <ctype.h>
#include <functional>
#include <iostream>
#include <limits.h>
#include <locale.h>
#include <map>
#include <math.h>3
#include <queue>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <time.h>
#include <vector>
//#include <unordered_set>
//#include <unordered_map>

#pragma warning(disable:4996)
using namespace std;

#define mp make_pair
#define PB push_back
typedef long long ll;
typedef long long LL;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <ll, int> pli;
typedef pair <ldb, ldb> pdd;

int IT_MAX = 1 << 21;
const int MOD = 1000000007;
const int INF = 1034567891;
const ll LL_INF = 1234567890123456789ll;
const db PI = 3.141592653589793238;
const ldb ERR = 1E-12;
const ll mod = 1e6+3 ;
ll qpow(ll x, ll y){
    if(y == 0) return 1 ;
    ll tmp = qpow(x , y/2) ;
    if(y & 1) return tmp * tmp % mod * x % mod ;
    return tmp * tmp % mod ;
}
#define mem(x ,y ) memset(x , y , sizeof(x))
#define lowbit(x) (x & (-x))
/****/
/****/
vector <int> v[200010] ;
multiset<int>q[200010] ;
map <int,ll> sum ;
int a[200010] ;
int b[200010] ;
ll ans = 0 ;
ll n , m ;
void unionset(int i ,int j){
    if(q[i].size() < q[j].size()) swap(q[i] , q[j]) , swap(sum[i] ,sum[j]) ;
    sum[i] += sum[j] ;
    for(multiset<int>::iterator mi=q[j].begin() ; mi!=q[j].end() ; mi++){
        int x = *mi;
        q[i].insert(x) ;
    }
    multiset<int,int>::iterator mi=q[i].end() ; mi -- ;
    multiset<int,int>::iterator tmp ;
    int sz = q[i].size() ;
    while(sz && sum[i] > m){
        int x = *mi ;
        q[i].erase(mi --);
        sum[i] -= x ; sz -- ;
    }
}
void dfs(int ts){
    if(ts != 0){
        q[ts].insert(a[ts]) ;
        sum[ts] += a[ts] ;
    }
    for(int i=0;i<v[ts].size() ; i++){
        int e = v[ts][i] ;
        dfs(e) ;
        if(ts != 0) unionset(ts , e) ;
    }
    if(ts!=0) ans = max(ans , (ll)q[ts].size() * b[ts]) ;
}
int main() {
    cin >> n >> m ;
    for(int i=1;i<=n;i++){
        int ta,tb,tc; scanf("%d%d%d" , &ta,&tb,&tc) ;
        v[ta].PB(i) ;
        a[i] = tb ; b[i] = tc ;
    }
    dfs(0) ;
    cout << ans <<endl ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值