最大利润
题目大意
你在火车站开饭店,但不允许同时在两个相连接的火车站开。任意两个火车站有且只有一条路径,每个火车站最多有50个和它相连接的火车站。
告诉你每个火车站的利润,问你可以获得的最大利润为多少。
样例输入
6
10
20
25
40
30
30
4 5
1 3
3 4
2 3
6 4
样例输出
90
数据范围
N<=100000
思路
这道题我们用数位dp来做。
我们先用邻接表来存储每一条线。然后用
f
[
i
]
[
1
]
f[i][1]
f[i][1]来表示第i个车站建餐厅,相邻的车站只能不建(用
f
[
i
]
[
0
]
f[i][0]
f[i][0]表示第i个车站不建)。所以于不建的车站相邻的车站可以建也可以不建,我们选利润最大的。
就这样一直推下去,最后输出f[1][1]和f[1][0]中的较大值就行了。
代码
#include<cstdio>
#include<iostream>
using namespace std;
int p[100001],f[100001][3],s[100001],le[100001],n,x,y,w;
struct note
{
int to,next;
}e[200001];
int dfs(int sum)
{
f[sum][1]=s[sum];//自己的
p[sum]=1;//标记
for (int i=le[sum];i;i=e[i].next)//枚举于这个点相邻的每一条边
if (!p[e[i].to])//判断是否去过
{
dfs(e[i].to);//递归
f[sum][1]+=f[e[i].to][0];//建
f[sum][0]+=max(f[e[i].to][1],f[e[i].to][0]);//不建
}
p[sum]=0;//回溯
}
int main()
{
// freopen("profit.in","r",stdin);
// freopen("profit.out","w",stdout);
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);//读入
e[++w]=(note){y,le[x]};le[x]=w;//建邻接表
e[++w]=(note){x,le[y]};le[y]=w;//反向再建一个(因为路径为双向的)
}
dfs(1);
printf("%d",max(f[1][1],f[1][0]));//输出较大值
// fclose(stdin);
// fclose(stdout);
return 0;
}