提交时,注意选择所期望的编译器类型。
思路参考:点击打开链接
题目大意: 给定一颗无根树,求出一个字数,所有节点的权值之和最大。求出最大的数是多少。 题目思路: 对于每个结点的决策有2种,分别是选择和不选择,那么我们定义dp[ i ][ 0 ] 和 dp[ i ][ 1 ]分别表示不选择(选择) i 结点能得到的最大权值和。 状态转移方程是:dp [ i ] [ 1 ] = sum(max(dp[ j ][ 1 ] , dp[ j ][ 0 ])); j 是 i 的孩子结点 。 dp[ i ][ 0 ] = 0; 由于题目中给出的是无根树,所以在进行DFS的时候要进行标记,当要搜索的结点的孩子结点都曾经被访问过,那么他就是叶节点。也是就递归的边界(停止该分支的搜索)。
#include <cstdio> #include <algorithm> #include <vector> using namespace std; int n,p,q,ans=-1; int a[100010]; int dp[100010][2]; vector<int> v[100010]; bool vis[100010]; void dfs(int x) { dp[x][1]=a[x]; dp[x][0]=0; vis[x]=true; for (int i=0;i<v[x].size();i++) { if (!vis[v[x][i]]) { dfs(v[x][i]); dp[x][1]+=max(dp[v[x][i]][1],dp[v[x][i]][0]); } else { dp[x][1]=max(dp[x][1],a[x]); dp[x][0]=max(dp[x][0],0); } } return; } int main() { scanf ("%d",&n); for (int i=1;i<=n;i++) scanf ("%d",&a[i]); for (int i=1;i<n;i++) { scanf ("%d%d",&p,&q); v[p].push_back(q); v[q].push_back(p); } dfs(1); for (int i=1;i<=n;i++) { ans=max(ans,dp[i][0]); ans=max(ans,dp[i][1]); } printf ("%d\n",ans); return 0; }