[HEOI2015]兔子與櫻花 樹規+貪心
阿新 • • 發佈:2019-02-13
鬼能想到是個貪心。明明覺得是樹規啊。。又完美爆零。。
從葉子節點往上更新,能保證最優解(這塊想了半天)。 證明:當你的子樹上有能刪的點而你不刪時,可能會對子樹的根節點有利,最好的情況是使子樹根節點由不可刪除變為可刪除。但是,既然最終可能刪一個點,還不如直接刪現成能刪的呢。。 用wei[]記錄每個節點的權值(花數+兒子數),在更新結果時將權值更新即可。
從葉子節點往上更新,能保證最優解(這塊想了半天)。 證明:當你的子樹上有能刪的點而你不刪時,可能會對子樹的根節點有利,最好的情況是使子樹根節點由不可刪除變為可刪除。但是,既然最終可能刪一個點,還不如直接刪現成能刪的呢。。 用wei[]記錄每個節點的權值(花數+兒子數),在更新結果時將權值更新即可。
#include #include #include #include #include #include using namespace std; #define pos(i,a,b) for(int i=(a);i<=(b);i++) #define N 2000500 int n,m; vector son[N]; int wei[N]; int ji[N]; int ans; bool tmp(const int &a,const int &b) { return wei[a] } void dp(int x) { if(ji[x]==0) return; pos(i,0,ji[x]-1) { dp(son[x][i]); } sort(son[x].begin(),son[x].end(),tmp); pos(i,0,ji[x]-1) { if(wei[x]-1+wei[son[x][i]]<=m) { ans++; wei[x]+=wei[son[x][i]]-1; } } } int main() { freopen("sakura.in","r",stdin); freopen("sakura.out","w",stdout); cin>>n>>m; pos(i,1,n) scanf("%d",&wei[i]); pos(i,1,n) { scanf("%d",&ji[i]); wei[i]+=ji[i]; pos(j,1,ji[i]) { int p; scanf("%d",&p); p++; son[i].push_back(p); } } dp(1); cout<<ans; //while(1); return 0; }