貪心 A 兔子與櫻花

2021-10-08 14:58:52 字數 1464 閱讀 2080

兔子與櫻花原題

需要求出最大的可以刪除的節點的數量。

我們從葉子節點開始刪。為什麼不從別的節點開始呢?假設我們不從葉子節點開始,那麼每一次的刪除都需要考慮節點的父節點的權重與該節點的權重和子節點的數量,而如果我們從葉子節點開始,只需要考慮節點的權重與其父節點的權重即可。相對而言比較簡單。

要刪除的葉子節點最多,就需要刪除的節點的權重盡可能小。這樣,集中到其父節點的權重也會盡可能地小,可刪除的節點就會增多。

首先,要去找葉子節點,可以用深度優先搜尋。

之後,每次都需要刪除當前最小的權重,可以用排序或者優先佇列。

#include#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

//#pragma gcc optimize(2)

#define io ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

#define ull unsigned long long

#define ll long long

#define rep(i, x, y) for(int i=x;i<=y;i++)

#define mms(x, n) memset(x, n, sizeof(x))

#define mmc(a, b) memcpy(a, b, sizeof(b))

#define inf (0x3f3f3f3f)

#define mod (ull)(1e9+7)

typedef pairp;

namespace fastio

return buf[tot];

}inline int read()

}using fastio::read;

// 洛谷的該題不用快讀會tle。

const int n = 2e6 + 10;

int c[n];

vectorson[n];

int ans;

int n, m;

bool cmp(int a, int b)

void dfs(int node)

sort(son[node].begin(), son[node].end(), cmp);

for (int i = 0; i < size; i++) else break;

}}int main()

for (int i = 0; i < n; i++)

}dfs(0);

printf("%d", ans);

return 0;

}

BZOJ4027 兔子與櫻花(貪心)

bzoj 洛谷很直觀的乙個感受就是對於每個節點,考慮它的所有兒子,如果能刪就刪。那麼我們把所有兒子按照給刪去後給父親c i c i 的貢獻從小往大排序,能刪就刪即可。include include using namespace std define ll long long define max ...

P4107 HEOI2015 兔子與櫻花 貪心

傳送門 一道貪心題 首先我們可以證明最優的貢獻一定是從下依次合併到上的 不會出現乙個節點不能合併到父親節點,卻能合併到父親節點的祖先節點的情況 我們設當前的節點為 u u 的父親節點為 v v 的父親節點是 fa 如果 u 不能合併到 v 上,那麼必定有 c u son u 1 c v son v ...

兔子與櫻花(sakura) 題解

outline給一棵樹,編號為0 n 1,樹有承重值m,每個節點的承重為自身價值c i 加上其孩子個數son i 這不科學啊,不應該是整個子樹的價值嗎?每刪乙個節點,就將其孩子連向其父親,自己的價值加進其父親的價值中,並保證滿足承重要求 承重不超過m 求其節點最多能刪幾個?input第一行輸入兩個正...