树形dp.docx
《树形dp.docx》由会员分享,可在线阅读,更多相关《树形dp.docx(29页珍藏版)》请在冰豆网上搜索。
![树形dp.docx](https://file1.bdocx.com/fileroot1/2023-1/8/26f425ae-e6a3-4ba1-9e29-356cae23b083/26f425ae-e6a3-4ba1-9e29-356cae23b0831.gif)
树形dp
树形dp
Anniversaryparty
TimeLimit:
2000/1000MS(Java/Others) MemoryLimit:
65536/32768K(Java/Others)
TotalSubmission(s):
7954 AcceptedSubmission(s):
3462
ProblemDescription
Thereisgoingtobeapartytocelebratethe80-thAnniversaryoftheUralStateUniversity.TheUniversityhasahierarchicalstructureofemployees.ItmeansthatthesupervisorrelationformsatreerootedattherectorV.E.Tretyakov.Inordertomakethepartyfunnyforeveryone,therectordoesnotwantbothanemployeeandhisorherimmediatesupervisortobepresent.Thepersonnelofficehasevaluatedconvivialityofeachemployee,soeveryonehassomenumber(rating)attachedtohimorher.Yourtaskistomakealistofguestswiththemaximalpossiblesumofguests'convivialityratings.
Input
Employeesarenumberedfrom1toN.AfirstlineofinputcontainsanumberN.1<=N<=6000.EachofthesubsequentNlinescontainstheconvivialityratingofthecorrespondingemployee.Convivialityratingisanintegernumberinarangefrom-128to127.AfterthatgoTlinesthatdescribeasupervisorrelationtree.Eachlineofthetreespecificationhastheform:
LK
ItmeansthattheK-themployeeisanimmediatesupervisoroftheL-themployee.Inputisendedwiththeline 00
Output
Outputshouldcontainthemaximalsumofguests'ratings.
SampleInput
7
1
1
1
1
1
1
1
13
23
64
74
45
35
00
SampleOutput
5
题意:
一个公司要举办party,不过每一个员工都不愿意和自己的上级在一起,因为这样自己会不开心,而每个人参加party都有一个开心的程度,同时给出来上下级之间的关系,让我们求最大的开心程度是多少。
这题用来树形dp入门,首先就是如何来建树的问题和怎样dp的问题,我们直接用一个数组f[i]来表示第i个人的上司是谁,这样通过层层递进来找到最大的大boss,也就是一棵树的根,然后,用dfs的方式来进行层层搜索,同时dp。
具体的dp过程也就是用dp[i][0]表示如果这个人不来时候的最大开心程度,dp[i][1]表示这个人来的时候的最大开心程度,如果树上面的父亲节点x不来,那么dp[x][0]+=max(dp[i][0],dp[i][1]);,如果树上的父亲节点x来(意味着子节点不会来),那么dp[x][1]+=dp[i][0];
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
typedeflonglongll;
constintN=6010;
intm,n;
intdp[N][2],rd[N];
vectortu[N];
voiddfs(intx)
{
intl=tu[x].size();
for(inti=0;i{
intt=tu[x][i];
dfs(t);
dp[x][0]+=max(dp[t][1],dp[t][0]);
dp[x][1]+=dp[t][0];
}
}
intmain()
{
while(~scanf("%d",&n))
{
for(inti=1;i<=n;i++)
tu[i].clear();
memset(rd,0,sizeof(rd));
for(inti=1;i<=n;i++)
{
scanf("%d",&dp[i][1]);
dp[i][0]=0;
}
intx,y;
while(~scanf("%d%d",&x,&y)&&x+y)
tu[y].push_back(x),rd[x]++;
intans=-1;
for(inti=1;i<=n;i++)
if(rd[i]==0)///防止不止一个根节点
{dfs(i);ans=max(ans,max(dp[i][0],dp[i][1]));}
cout<}
}
Themore,TheBetter
TimeLimit:
6000/2000MS(Java/Others) MemoryLimit:
32768/32768K(Java/Others)
TotalSubmission(s):
6868 AcceptedSubmission(s):
4033
ProblemDescription
ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。
但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。
你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗?
Input
每个测试实例首先包括2个整数,N,M.(1<=M<=N<=200);在接下来的N行里,每行包括2个整数,a,b.在第i行,a代表要攻克第i个城堡必须先攻克第a个城堡,如果a=0则代表可以直接攻克第i个城堡。
b代表第i个城堡的宝物数量,b>=0。
当N=0,M=0输入结束。
Output
对于每个测试实例,输出一个整数,代表ACboy攻克M个城堡所获得的最多宝物的数量。
SampleInput
32
01
02
03
74
22
01
04
21
71
76
22
00
SampleOutput
5
13
虽然是树形dp,可是其dp方式看起来有点像区间dp(总归来说,其实二维dp也就是这样的了。
。
)
这题的dp有点不好想,不过其实仔细看还是可以看懂的。
。
。
用dp[i][j]表示第i个点攻克j个城堡获得的最大财富。
若t是i的一个子节点,那么dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[t][k]);
这个dp方程真心不好想。
。
还有一点是我们要防止j大于了m,所以dfs里边加上一个变量,使最多只有m次。
当然,我首先就把m++了,因为我引入了0这个节点来连接所有树的根节点,这样就做到了把森林连成了树!
#include
#include
#include
#include
#include
#include
#include
#definem(a,b)memset(a,b,sizeof(a))
usingnamespacestd;
typedeflonglongll;
constintN=250;
intdp[N][N],vis[N];
intm,n;
vectortu[N];
voiddfs(intx,intmm)
{
vis[x]=1;
intl=tu[x].size();
for(inti=0;i{
intt=tu[x][i];
if(!
vis[t])
dfs(t,mm-1);
for(intj=mm;j>=1;j--)//j的上下界比较好想,不过一定要注意j是从大到小在变化的。
for(intk=1;kdp[x][j]=max(dp[x][j],dp[x][j-k]+dp[t][k]);
}
}
intmain()
{
while(cin>>n>>m&&m+n)
{
m++;
m(dp,0);
m(tu,0);
m(vis,0);
for(inti=1;i<=n;i++)
{
inta,b;
cin>>a>>b;
tu[a].push_back(i);
dp[i][1]=b;
}
dfs(0,m);
printf("%d\n",dp[0][m]);
}
return0;
}
F.ZublicanesandMumocrates
timelimitpertest
3seconds
memorylimitpertest
512megabytes
input
standardinput
output
standardoutput
It'selectiontimeinBerland.Thefavoritesareofcoursepartiesofzublicanesandmumocrates.Theelectioncampaignsofbothpartiesincludenumerousdemonstrationson n mainsquaresofthecapitalofBerland.Eachofthe n squarescertainlycanhavedemonstrationsofonlyoneparty,otherwiseitcouldleadtoriots.Ontheotherhand,bothpartieshaveappliedtohostahugenumberofdemonstrations,sothatonallsquaresdemonstrationsmustbeheld.Nowthecapitalmanagementwilldistributetheareabetweenthetwoparties.
Somepairsofsquaresareconnectedby (n - 1) bidirectionalroadssuchthatbetweenanypairofsquaresthereisauniquewaytogetfromonesquaretoanother.Somesquaresareontheoutskirtsofthecapitalmeaningthattheyareconnectedbyaroadwithonlyoneothersquare,suchsquaresarecalled deadend squares.
Themayorofthecapitalinstructedtodistributeallthesquaresbetweenthepartiessothatthe deadend squareshadthesamenumberofdemonstrationsofthefirstandthesecondparty.Itisguaranteedthatthenumberofdeadendsquaresofthecityiseven.
Topreventpossibleconflictsbetweenthezublicanesandthemumocratesitwasdecidedtominimizethenumberofroadsconnectingthesquareswiththedistinctparties.You,asadeveloperofthedepartmentofdistributingsquares,shoulddeterminethissmallestnumber.
Input
Thefirstlineoftheinputcontainsasingleinteger n (2 ≤ n ≤ 5000)—thenumberofsquaresinthecapitalofBerland.
Next n - 1 linescontainthepairsofintegers x, y (1 ≤ x, y ≤ n, x ≠ y)—thenumbersofthesquaresconnectedbytheroad.Allsquaresarenumberedwithintegersfrom 1 to n.Itisguaranteedthatthenumberofdeadendsquaresofthecityiseven.
Output
Printasinglenumber—theminimumnumberofroadsconnectingthesquareswithdemonstrationsofdifferentparties.
Sampletest(s)
input
8
14
24
34
65
75
85
45
output
1
input
5
12
13
14
15
output
2
题意:
给出一个树,要求最少删除多少条边之后使叶子节点恰好平分。
思路:
树形dp,用dp[i][j]表示节点i删除j个叶子节点所需要的最短的步数
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
typedeflonglongll;
constintN=5001,INF=999999999;
vectortu[N];
intz[N];///某个节点的叶子节点数
intdp[N][N];///dp[i][j]表示叶子节点i删除j个节点所需要的最短的步数
intn;
voiddfs(intnow,intpre)
{
if(tu[now].size()==1)
z[now]=1;
elsez[now]=0;
dp[now][0]=0;
for(inti=1;i<=n;i++)
dp[now][i]=INF;
intl=tu[now].size();
for(inti=0;i{
intnext=tu[now][i];
if(next==pre)continue;
dfs(next,now);
for(intj=z[now];j>=0;j--)///必须逆序
for(intk=0;k<=z[next];k++)
dp[now][j+k]=min(dp[now][j+k],dp[now][j]+dp[next][k]);///状态转移
z[now]+=z[next];
}
for(inti=0;i<=z[now];i++)
dp[now][i]=min(dp[now][i],dp[now][z[now]-i]+1);///把now节点算进去,删除i个叶节点相当于一刀把now节点连接父亲的边删掉(所有叶节点删掉之后,相当于代码+1操作)再把z[now]-i个本来不打算删掉的叶节点删回来
}
intmain()
{
scanf("%d",&n);
if(n==2)
{
puts("1");
return0;
}
memset(dp,0,sizeof(dp));
for(inti=0;i{
inta,b;
scanf("%d%d",&a,&b);
tu[a].push_back(b);
tu[b].push_back(a);
}
introot=1;
while(tu[root++].size()==1);
dfs(root,0);
printf("%d\n",dp[root][z[root]/2]);
}
Mahjongtree
TimeLimit:
6000/3000MS(Java/Others) MemoryLimit:
65536/65536K(Java/Others)
TotalSubmission(s):
1660 AcceptedSubmission(s):
521
ProblemDescription
Littlesunisanartist.Todayheisplayingmahjongalone.Hesuddenlyfeelsthatthetreeintheyarddoesn'tlookgood.Sohewantstodecoratethetree.(Thetreehasnvertexs,indexedfrom1ton.)
Thoughtforalongtime,finallyhedecidestousethemahjongtodecoratethetree.
Hismahjongisstrangebecauseallofthemahjongtileshadadistinctindex.(Littlesunhasonlynmahjongtiles,andthemahjongtilesindexedfrom1ton.)
Heputthemahjongtilesonthevertexsofthetree.
Asisknowntoall,littlesunisanartist.Sohewanttodecoratethetreeasbeautifulaspossible.
Hisdecorationrulesareasfollows:
(1)Placeexactonemahjongtileoneachvertex.
(2)Themahjongtiles'indexmustbecontinueswhichareplacedonthesonvertexsofavertex.
(3)Themahjongtiles'indexmustbecontinueswhichareplacedonthevertexsofanysubtrees.
Nowhewanttoknowthathecanobtainhowmanydifferentbeautifulmahjongtreeusingtheserules,becauseoftheanswercanbeverylarge,youneedoutputtheanswermodulo1e9+7.
Input
ThefirstlineoftheinputisasingleintegerT,indicatesthenumberoftestcases.
Foreachtestcase,thefirstlinecontainsanintegersn.(1<=n<=100000)
Andthenextn-1lines,eachlinecontainstwointegersuiandvi,whichdescribesanedgeofthetree,andvertex1istherootofthetree.
Output
Foreachtestcase,outputoneline.Theoutputformatis"Case#x:
ans"(withoutquotes),xisthecasenumber,startingfrom1.
SampleInput
2
9
21
31
43
53
62
74
87
93
8
21
31
43
51
64
75
84
SampleOutput
Case#1:
32
Case#2:
16
题意:
有一棵有n个节点的树,有编号1~n的n个数字要放到树上,且要满足三个要求:
1.树的每个节点只放一个数字
2.树的任意一个节点的所有直接孩子节点上面放的数字排序后是连续的
3.一棵子树的所有节点上面放的数字排序后是连续的
问有多少种不同的放法,结果取模1e9+7。
思路:
由于所有子树是连续的,所以可以用区间来表示子树,设要给当前子树编号为[1,n],如果当前子树是原树,那么根有两种选择,分别是放头和尾(如果n等于1,那么头和尾重合了,也就是只有1种选择),如果不是原树,那么根的选择是唯