版权声明:欢迎借鉴,谢绝抄搬。 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;
}