二叉苹果树(树形dp)

二叉苹果树

题目描述

有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点。这棵树共N个节点,标号1至N,树根编号一定为1。
我们用一根树枝两端连接的节点编号描述一根树枝的位置。一棵有四根树枝的苹果树,因为树枝太多了,需要剪枝。但是一些树枝上长有苹果,给定需要保留的树枝数量,求最多能留住多少苹果。
二叉苹果树(树形dp)_第1张图片

输入描述:

第一行两个数N和Q,N表示树的节点数,Q表示要保留的树枝数量。
接下来N-1行描述树枝信息,每行三个整数,前两个是它连接的节点的编号,第三个数是这根树枝上苹果数量。

输出描述:

输出仅一行,表示最多能留住的苹果的数量。
示例1

输入

5 2
1 3 1
1 4 10
2 3 20
3 5 20

输出

21

备注:

对于100%的数据,1≤Q≤N≤100,N≠11,每根树枝上苹果不超过30000个。

题目思路:
f[i][j]表示以i为根节点的子树保留j根树枝的最多苹果数,d[i][j]表示i节点到j节点树枝上的苹果数。
vector作为邻接表记录与每个节点相邻的节点(注意dfs时不能走父节点)。
代码如下(记忆化搜索实现):
#include
#define ll long long
using namespace std;
int n,m,f[101][101],d[101][101];
vector v[101];
int dfs(int x,int y,int fa)
{
    vector child;
    int ans = 0;
    if(f[x][y]!=-1)
        return f[x][y];
    if(x!=1&&v[x].size()==1||y==0)
    {
        f[x][y] = ans;
        return ans;
    }
    else if(v[x].size()==2&&x!=1||x==1&&v[x].size()==1)
    {
        for(int i = 0;i=2)
	        for(int i = 0;i=1)
 		{
 			ans = max(ans,d[x][child[0]]+dfs(child[0],y-1,x));
 			ans = max(ans,d[x][child[1]]+dfs(child[1],y-1,x));
		}		      
        f[x][y] = ans;
        return ans;
    }
}
int main()
{
    memset(d,-1,sizeof(d));
    memset(f,-1,sizeof(f));
    int a,b,c;
    cin>>n>>m;
    for(int i = 0;i>a>>b>>c;
        v[a].push_back(b);
        v[b].push_back(a);
        d[a][b] = c;
        d[b][a] = c;
    }
    cout<

  

如果有错误的地方,还请各位大佬指正。

转载于:https://www.cnblogs.com/loganacmer/p/11296870.html

你可能感兴趣的:(数据结构与算法)