【链表】【树形DP】最大利润(jzoj 1487)

版权声明:欢迎借鉴,谢绝抄搬。 https://blog.csdn.net/ssllyf/article/details/86618874

最大利润

题目大意:

有n个车站,每个车站有一定的人数,有n-1条线路连接着这些车站,相邻的车站不能同时有两个餐厅,当在一个车站建立餐厅时,会得到这个车站所有人的monny(1个人可以得到1份利润),要使利润最大

样例输入

6

10

20

25

40

30

30

4 5

1 3

3 4

2 3

6 4

样例输出

90

数据范围限制

提示

数据说明:

n<=100000

解题思路:

这道题一看就要用到链表,我们用链表来存储每一条线,然后head是指某一个点连接的第一条线,然后用a的next引入其他线,然后用f[i][1]来表示第i个车站建餐厅,所以相邻的车站只能不建,用f[i][0]来表示第i个车站不建,所以相邻的车站可以建也可以不建(求最大的),然后一直推下去,最后输出f[1][1]和f[1][0]中最大的就行了

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int p[100005],f[100005][3],s[100005],head[100005],n,x,y,w;
struct rec//线
{
	int next,to;
}a[200005];
int js(int sum)
{
	f[sum][1]=s[sum];//自己那一份
	p[sum]=1;//记录
	for (int i=head[sum];i;i=a[i].next)//枚举连接sum的每一条线
	  if (!p[a[i].to])//没有去过
	    {
	    	js(a[i].to);//往下递归
	    	f[sum][1]+=f[a[i].to][0];//建了
	    	f[sum][0]+=max(f[a[i].to][1],f[a[i].to][0]);//没建
		}
	p[sum]=0;//清空
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	  scanf("%d",&s[i]);
	for (int i=1;i<n;i++)
	  {
	  	scanf("%d %d",&x,&y);
	  	a[++w].to=y//连接的点;
	  	a[w].next=head[x];//下一条线
	  	head[x]=w;//代替
	  	a[++w].to=x;//同上
	  	a[w].next=head[y];
	  	head[y]=w;
	  }
	js(1);//递归
	printf("%d",max(f[1][1],f[1][0]));//求最大的
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ssllyf/article/details/86618874
今日推荐