bzoj4027,[HEOI2015]兔子与樱花
題目鏈接:http://www.lydsy.com/JudgeOnline/problem.php?id=4027
Description
很久很久之前,森林里住著一群兔子。有一天,兔子們突然決定 要去看櫻花。兔子們所在森林里的櫻花樹很特殊。櫻花樹由n個樹枝分叉點(diǎn)組成,編號從0到n-1,這n個分叉點(diǎn)由n-1個樹枝連接,我們可以把它看成一個有 根樹結(jié)構(gòu),其中0號節(jié)點(diǎn)是根節(jié)點(diǎn)。這個樹的每個節(jié)點(diǎn)上都會有一些櫻花,其中第i個節(jié)點(diǎn)有c_i朵櫻花。櫻花樹的每一個節(jié)點(diǎn)都有最大的載重m,對于每一個節(jié) 點(diǎn)i,它的兒子節(jié)點(diǎn)的個數(shù)和i節(jié)點(diǎn)上櫻花個數(shù)之和不能超過m,即son(i) + c_i <= m,其中son(i)表示i的兒子的個數(shù),如果i為葉子節(jié)點(diǎn),則son(i) = 0
現(xiàn)在兔子們覺得櫻花樹上節(jié)點(diǎn)太多,希望去掉一些節(jié)點(diǎn)。當(dāng)一個節(jié)點(diǎn)被去掉之后,這個節(jié)點(diǎn)上的櫻花和它的兒子節(jié)點(diǎn)都被連到刪掉節(jié)點(diǎn)的父節(jié)點(diǎn)上。如果父節(jié)點(diǎn)也被刪除,那么就會繼續(xù)向上連接,直到第一個沒有被刪除的節(jié)點(diǎn)為止。 現(xiàn)在兔子們希望計(jì)算在不違背最大載重的情況下,最多能刪除多少節(jié)點(diǎn)。 注意根節(jié)點(diǎn)不能被刪除,被刪除的節(jié)點(diǎn)不被計(jì)入載重。Input
第一行輸入兩個正整數(shù),n和m分別表示節(jié)點(diǎn)個數(shù)和最大載重
第二行n個整數(shù)c_i,表示第i個節(jié)點(diǎn)上的櫻花個數(shù) 接下來n行,每行第一個數(shù)k_i表示這個節(jié)點(diǎn)的兒子個數(shù),接下來k_i個整數(shù)表示這個節(jié)點(diǎn)兒子的編號Output
?一行一個整數(shù),表示最多能刪除多少節(jié)點(diǎn)。
Sample Input
10 40 2 2 2 4 1 0 4 1 1
3 6 2 3
1 9
1 8
1 1
0
0
2 7 4
0
1 5
0
Sample Output
4HINT
對于100%的數(shù)據(jù),1 <= n <= 2000000, 1 <= m <= 100000, 0 <= c_i <= 1000,數(shù)據(jù)保證初始時,每個節(jié)點(diǎn)櫻花數(shù)與兒子節(jié)點(diǎn)個數(shù)之和大于0且不超過m
題解: 本來是想寫一下動歸的,在hzwer的博客的動歸題里翻了一下,然后看到樹形動規(guī),覺得蠻好的,就寫了一寫,然后,這是個貪心。。。合并的話,是吧兒子的權(quán)值,和兒子的后代傳給父親,那么很容易想到的是,如果當(dāng)前節(jié)點(diǎn)可以上傳,那么如果他的兒子可以上傳,盡量上傳他的兒子,這樣不會使結(jié)果更差,對答案的貢獻(xiàn)都是一個,而且如果當(dāng)前節(jié)點(diǎn)不上傳,對于之后節(jié)點(diǎn)的上傳會有好處。那么,可以得到一個貪心策略,可以把兒子能合并的盡量合并,先合并代價小的,再合并代價大的 代碼解釋: c[]存的是每一個節(jié)點(diǎn)的代價,包含了其兒子個數(shù),所以后面合并時要把兩者代價和減1 代碼: #include<iostream> #include<cstdlib> #include<cstdio> #include<algorithm> #define N 2000010 using namespace std; int sum,m,ans,n,T,p; int head[N],next[N],to[N]; int a[N],c[N]; int getint() {int res=0,w=1;char ch=getchar();while ((ch>'9' || ch<'0')&&ch!='-') ch=getchar();if (ch=='-') w=-1,ch=getchar();while (ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar();return res*w; } void link(int x,int y) {next[++sum]=head[x]; head[x]=sum; to[sum]=y;} void dfs(int p) {for (int i=head[p];i;i=next[i]) dfs(to[i]);int k=0;for (int i=head[p];i;i=next[i]) a[++k]=c[to[i]];sort(a+1,a+1+k);for (int i=1;i<=k;i++){if (c[p]+a[i]-1<=m)c[p]+=a[i]-1,ans++;else break;} } int main() {n=getint(); m=getint();for (int i=1;i<=n;i++) c[i]=getint();for (int i=1;i<=n;i++){T=getint(); c[i]+=T; while (T--) {p=getint()+1; link(i,p); }}dfs(1);printf("%d\n",ans);return 0; }?
轉(zhuǎn)載于:https://www.cnblogs.com/xiaoqiang200015/p/5977418.html
總結(jié)
以上是生活随笔為你收集整理的bzoj4027,[HEOI2015]兔子与樱花的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黄金白银、古董与收藏
- 下一篇: 【移动开发】安卓Lab2(02)