结点选择 搜索,dp思想

来源:互联网 发布:数据共享交换系统 编辑:程序博客网 时间:2024/04/29 01:16

1003: 结点选择

Time Limit: 1 Sec  Memory Limit: 128 MB  64bit IO Format: %lld
Submitted: 25  Accepted: 8
[Submit][Status][Web Board]

Description

有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少?

Input

多组测试数据
每组第一行包含一个整数 n 。
接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。
接下来一共 n-1 行,每行描述树上的一条边。

Output

输出一个整数,代表选出的点的权值和的最大值。

Sample Input 

51 2 3 4 51 21 32 42 5

Sample Output

12

HINT

样例说明

选择3、4、5号点,权值和为 3+4+5 = 12 。


数据规模与约定

对于20%的数据, n <= 20。

对于50%的数据, n <= 1000。

对于100%的数据, n <= 100000。

权值均为不超过1000的正整数。

#include <bits/stdc++.h>#include <iostream>#include <stdio.h>#include <string>#include <cstring>#include <cmath>#include <algorithm>#include <vector>using namespace std;int vis[100009];int dp[100009][2];vector<int>v[100009];int ans;void dfs(int x){    vis[x]=1;    for(int i=0;i<v[x].size();i++)    {        int y=v[x][i];        if(vis[y])continue;        dfs(y);        dp[x][1]+=dp[y][0]; //选父节点那么不选子节点        dp[x][0]+=max(dp[y][0],dp[y][1]);//不选父节点那么选或者不选子节点    }    ans=max(ans,dp[x][0]);    ans=max(ans,dp[x][1]);}int main(){    int n;    while(~scanf("%d",&n))    {        for(int i=0;i<=n;i++)v[i].clear();        memset(vis,0,sizeof vis);        memset(dp,0,sizeof dp);        for(int i=1;i<=n;i++)        {            scanf("%d",&dp[i][1]);        }        int x,y;        for(int i=1;i<n;i++)        {            scanf("%d%d",&x,&y);            v[x].push_back(y);            v[y].push_back(x);        }        ans=0;        dfs(1);        printf("%d\n",ans);    }    return 0;}






0 0
原创粉丝点击