2265 -- 【模拟试题】最大利润
Description
政府邀请了你在火车站开饭店,但不允许同时在两个相连的火车站开。任意两个火车站有且只有一条路径,每个火车站最多有50个和它相连接的火车站。
告诉你每个火车站的利润,问你可以获得的最大利润为多少?
Input
第一行输入整数N(<=100000),表示有N个火车站,分别用1,2,……..,N来编号。接下来N行,每行一个整数表示每个站点的利润,接下来N-1行描述火车站网络,每行两个整数,表示相连接的两个站点。
Output
输出一个整数表示可以获得的最大利润。
Sample Input
6
10
20
25
40
30
30
4 5
4 6
3 4
1 3
2 3
Sample Output
另外,与这个相似的题有:
Description
政府邀请了你在火车站开饭店,但不允许同时在两个相连的火车站开。任意两个火车站有且只有一条路径,每个火车站最多有50个和它相连接的火车站。
告诉你每个火车站的利润,问你可以获得的最大利润为多少?
Input
第一行输入整数N(<=100000),表示有N个火车站,分别用1,2,……..,N来编号。接下来N行,每行一个整数表示每个站点的利润,接下来N-1行描述火车站网络,每行两个整数,表示相连接的两个站点。
Output
输出一个整数表示可以获得的最大利润。
Sample Input
6
10
20
25
40
30
30
4 5
4 6
3 4
1 3
2 3
Sample Output
90
树形动规,f[point][bool_flag]表示取或不取当前点的时候取得的最大利润。
状态转移方程:
f[v][1]+=f[to][0];
f[v][0]+=max(f[son][1],f[son][0]);
注意要建双向边,DP时随便找一个点开始即可。
另外,DP传一个参数father_point来保证不走成环了。
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
int n,M;
int fa[600005]={0},val[600005]={0},f[600005][2]={0};
struct Edge
{
int next,to;
}w[1000005];
int cnt=0,h[100005]={0};
void Addarc(int x,int y)
{
cnt++;w[cnt].to=y;w[cnt].next=h[x];h[x]=cnt;
}
void DP(int v,int fa)
{
f[v][1]=val[v];
f[v][0]=0;
for(int i=h[v];i;i=w[i].next)
{
int to=w[i].to;
if(to==fa)continue;
DP(to,v);
f[v][1]+=f[to][0];//要这个点,就不能要儿子
f[v][0]+=max(f[to][1],f[to][0]);//不要这个点,可要也可不要儿子,因为存在负的欢乐值。
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",val+i);
for(int i=1;i<n;i++)
{
int K,L;
scanf("%d%d",&L,&K);
Addarc(K,L);
Addarc(L,K);
}
DP(1,0);
printf("%d",max(f[1][1],f[1][0]));
return 0;
}
另外,与这个相似的题有:
没有上司的聚会 (建的是单向边)
以及:
和:
加分二叉树 (基础题)