1. 程式人生 > >BZOJ2809 dispatching

BZOJ2809 dispatching

printf 這一 private ack 容易 維護 aps pan 數量

題目大意

  給你一棵有根樹,每個節點內有兩個值:領導力和費用。現要求選擇一個子樹,並在子樹內選擇若幹個節點,使得選擇的節點的費用總和不超出預算,且子樹的根的領導力乘以選擇的節點的數量的值最大。

思路

  由貪心思想,處理每個子樹時,我們優先保留費用低的節點,當節點的總費用超出預算時,我們優先去除費用最高的節點。貪心的優越正確性顯然。要達到這一點,我們很容易想到用大根堆來維護。問題在於,怎麽生成這個堆呢?可以看到一個子樹的堆可以由它的各個子樹的堆合並而成。所以我們的堆用可並堆。按照Dfs後序遍歷處理各個子樹即可。

註意事項

  • 堆合並後,要更新堆的根。
  • 註意運算時要開long long。
技術分享圖片
#include <cstdio>
#include 
<cstring> #include <algorithm> #include <vector> using namespace std; const int MAX_NODE = 100010; template<class KeyType> struct Heap { private: struct Node { Node *Father, *LeftSon, *RightSon; int Dist, Size; KeyType Key, Sum; Node(
int key) : Father(NULL), LeftSon(NULL), RightSon(NULL), Key(key), Sum(key), Dist(0), Size(1) {} void Refresh() { Dist = RightSon ? RightSon->Dist + 1 : 0; Sum = Key; Size = 1; if (LeftSon) { Sum = Sum + LeftSon->Sum; Size
+= LeftSon->Size; } if (RightSon) { Sum = Sum + RightSon->Sum; Size += RightSon->Size; } } }*Root; Node *Merge(Node *a, Node *b) { if(!a) return b; if (!b) return a; if(a->Key < b->Key) swap(a, b); a->RightSon = Merge(a->RightSon, b); if(a->RightSon) a->RightSon->Father = a; if((a->LeftSon ? a->LeftSon->Dist : 0) < (a->RightSon ? a->RightSon->Dist : 0)) swap(a->LeftSon, a->RightSon); a->Refresh(); return a; } public: Heap() :Root(NULL){} void Intake(Heap *a) { Root = Merge(Root, a->Root); } void Push(KeyType key) { Root = Merge(Root, new Node(key)); } void Pop() { Root = Merge(Root->LeftSon, Root->RightSon); } KeyType Sum() { if(!Root) return 0; return Root->Sum; } int Size() { if (!Root) return 0; return Root->Size; } }; struct Graph { private: int M; long long Ans; struct Node { vector<Node*> Sons; int Cost, Val; Node(){} Node(int cost, int val) : Cost(cost), Val(val) {} }_nodes[MAX_NODE], *Root; int _vCount; Heap<long long> *Dfs(Node *cur) { Heap<long long> *curHeap = new Heap<long long>(); if (cur == NULL) return curHeap; for (int i = 0; i < cur->Sons.size(); i++) curHeap->Intake(Dfs(cur->Sons[i])); curHeap->Push(cur->Cost); while (curHeap->Sum() > M) curHeap->Pop(); Ans = max(Ans, (long long)cur->Val * (long long)curHeap->Size()); return curHeap; } public: void Init(int n, int m) { _vCount = n; M = m; Ans = 0; } void SetNode(int cur, int fa, int cost, int val) { if(fa != 0) _nodes[fa].Sons.push_back(_nodes + cur); else Root = _nodes + cur; _nodes[cur].Cost = cost; _nodes[cur].Val = val; } long long GetAns() { Dfs(Root); return Ans; } }g; int main() { int totNode, m, fa, cost, val; scanf("%d%d", &totNode, &m); g.Init(totNode, m); for (int i = 1; i <= totNode; i++) { scanf("%d%d%d", &fa, &cost, &val); g.SetNode(i, fa, cost, val); } printf("%lld\n", g.GetAns()); return 0; }
View Code

BZOJ2809 dispatching