[BZOJ4027][HEOI2015]兔子與櫻花
阿新 • • 發佈:2018-08-07
vector const 刪除 edge 櫻花 tps urn 它的 tdi 從小到大能刪則刪。因為刪除一個兒子\(v\)只會增大\(u\)的\(g_u\)導致\(u\)可能刪不掉,所以這樣刪一定是不會使答案更劣的。
bzoj
luogu
description
一棵\(n\)個點的樹,每個點上有一個權值\(c_i\)。你可以刪掉任意一個除根之外的節點,刪除後這個點的權值和兒子都會轉移到它的父親上去。每個點需要滿足\(c_i+son(i)\le m\),其中\(son(i)\)是\(i\)節點的兒子個數。求最多可以刪掉多少個點。
\(n\le2\times10^6\)
sol
設\(f_i\)表示\(i\)點子樹內最多可以刪多少個點,\(g_i\)表示在\(i\)子樹內達成最優策略時,\(i\)號點的\(c_i+son(i)\)是多少。
對於一個點\(u\),考慮它的所有兒子刪還是不刪。一個貪心的結論是:按照\(g_v\)
code
辣雞\(\mbox{bzoj}\)不支持\(\mbox{-std=c++11}\)
#include<cstdio> #include<algorithm> #include<cstring> #include<vector> using namespace std; int gi(){ int x=0,w=1;char ch=getchar(); while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if (ch=='-') w=0,ch=getchar(); while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return w?x:-x; } const int N = 2e6+5; int n,m,f[N],g[N],tmp[N]; vector<int>edge[N]; void dfs(int u){ for (auto v:edge[u]) dfs(v),f[u]+=f[v]; int len=0; for (auto v:edge[u]) tmp[++len]=g[v]-1; sort(tmp+1,tmp+len+1); for (int i=1;i<=len;++i) if (g[u]+tmp[i]<=m) g[u]+=tmp[i],++f[u]; } int main(){ n=gi();m=gi(); for (int i=1;i<=n;++i) g[i]=gi(); for (int i=1;i<=n;++i){ int k=gi();g[i]+=k; while (k--) edge[i].push_back(gi()+1); } dfs(1);printf("%d\n",f[1]); return 0; }
[BZOJ4027][HEOI2015]兔子與櫻花