BZOJ 4027: [HEOI2015]兔子與櫻花

Description

很久很久之前,森林裏住着一羣兔子。有一天,兔子們突然決定要去看櫻花。兔子們所在森林裏的櫻花樹很特殊。櫻花樹由n個樹枝分叉點組成,編號從0n1 ,這n 個分叉點由n1 個樹枝連接,我們可以把它看成一個有根樹結構,其中0 號節點是根節點。這個樹的每個節點上都會有一些櫻花,其中第i 個節點有ci 朵櫻花。櫻花樹的每一個節點都有最大的載重m ,對於每一個節點i ,它的兒子節點的個數和i節點上櫻花個數之和不能超過m ,即son(i)+ci<=m ,其中son(i) 表示i的兒子的個數,如果i 爲葉子節點,則son(i)=0

現在兔子們覺得櫻花樹上節點太多,希望去掉一些節點。當一個節點被去掉之後,這個節點上的櫻花和它的兒子節點都被連到刪掉節點的父節點上。如果父節點也被刪除,那麼就會繼續向上連接,直到第一個沒有被刪除的節點爲止。
現在兔子們希望計算在不違背最大載重的情況下,最多能刪除多少節點。
注意根節點不能被刪除,被刪除的節點不被計入載重。

Solution

誒竟然1A了,不可思議。
這個貪心感覺很奇怪。。
首先如果v 和它的一個子節點t 合併了,那麼這個節點的載重變成了c[v]+c[t]+son[v]son[t]1 ,那麼我們按照c[t]son[t] 排序來更新點即可咯。
還有一件事就是如果點A 可以刪B ,點B 可以刪C ,但B 刪了C 就不可以和A 並了,該怎麼決策?
反正都是縮一個,觀察,若縮下面,就這樣,但縮上面,可能干擾其它點縮,並且下面的也不可能再縮上去,虧了,所以縮下面即可。

那麼就是一遍dfs可以搞定的事情了。

Code

/**************************************************************
    Problem: 4027
    User: bblss123
    Language: C++
    Result: Accepted
    Time:4696 ms
    Memory:61080 kb
****************************************************************/

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define pb push_back
#define ph push
#define vecn vector<node>
#define pqn priority_queue<node>
#define debug cout<<#x<<" "<<x<<endl;
#define frt fisrt
#define snd second
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vec;
typedef priority_queue<int> pq;
const int INF=1<<30;
const ll inf=1ll<<60;
const int M=2e6+5;
inline void Max(int &a,int b){if(a<b)a=b;}
inline void Min(int &a,int b){if(a>b||a==-1)a=b;}
inline void rd(int &a){
    a=0;char c;
    while(c=getchar(),!isdigit(c));
    do a=a*10+(c^48);
        while(c=getchar(),isdigit(c));
}
inline void work(ll x){
    if(!x)return;
    work(x/10);
    putchar(48+x%10);
}
inline void print(ll x){
    if(!x)putchar('0');
    else work(x);
}
int n,m,c[M],son[M],ans;
vec G[M];
struct node{
    int val,x;
    inline bool operator < (const node &tmp)const{
        return val>tmp.val;
    }
};
inline void dfs(int v){
    pqn que;for(;!que.empty();)que.pop();
    for(int i=0;i<G[v].size();++i){
        int to=G[v][i];
        dfs(to);
        que.push((node){c[to]+son[to],to});
    }
    for(;!que.empty();){
        node u=que.top();que.pop();
        if(c[v]+son[v]+u.val-1<=m){
            c[v]+=c[u.x],son[v]+=son[u.x]-1;
            ++ans;
        }
        else break;
    }
}
//////////////////////////////////////////////////////////////////////////////////////////////
//#define LOCAL
//////////////////////////////////////////////////////////////////////////////////////////////
int main(){
#ifdef LOCAL
    freopen("data.in","r",stdin);
    freopen("data.out","w",stdout);
#endif
    cin>>n>>m;
    for(int i=0;i<n;++i)
        rd(c[i]);
    for(int i=0;i<n;++i){
        rd(son[i]);
        for(int j=1,a;j<=son[i];++j)
            rd(a),G[i].pb(a);
    }
    dfs(0);
    cout<<ans<<endl;
    return 0;
}
發佈了80 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章