树形DP经典题

题目传送门

题意:

给出一棵树,求离每个节点最远的点的距离

思路:

把无根树转化成有根树分析,

对于上面那棵树,要求距结点2的最长距离,那么,就需要知道以2为顶点的子树(蓝色圈起的部分,我们叫它Tree(2)),距顶点2的最远距离L1

还有知道2的父节点1为根节点的树Tree(1)-Tree(2)部分(即红色圈起部分),距离结点1的最长距离+dist(1,2) = L2,那么最终距离结点2最远的距离就是max{L1,L2}

f[i][0],表示顶点为i的子树的,距顶点i的最长距离

f[i][1],表示Tree(i的父节点)-Tree(i)的最长距离+i跟i的父节点距离

要求所有的f[i][0]很简单,只要先做一次dfs求每个结点到叶子结点的最长距离即可。

然后要求f[i][1], 可以从父节点递推到子节点,

假设节点u有n个子节点,分别是v1,v2...vn

那么

如果vi不是u最长距离经过的节点,f[vi][1] = dist(vi,u)+max(f[u][0], f[u][1])

如果vi是u最长距离经过的节点,那么不能选择f[u][0],因为这保存的就是最长距离,要选择Tree(u)第二大距离secondDist,

可得f[vi][1] = dist(vi, u) + max(secondDist, f[u][1])

贴一段自己AC的代码:

<pre name="code" class="cpp">//求树的最长路径问题
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 10100
struct node
{
    int id;
    int next;
    int len;
};

struct node edge[MAXN*2];
int head[MAXN];  //用来表示头节点
int d[MAXN][2];  //用来表示状态集
int smaxn[MAXN];//次大距离
int smaxnid[MAXN]; //次最大值所经过的子节点
int maxnid[MAXN];  //最大值所经过的子节点
int ptr;

void init()
{
    ptr=0;
    memset(head,-1,sizeof(head));
}

void addEdge(int a,int b,int len)  //树形DP模版和上一篇一样的
{
    edge[ptr].id=b;
    edge[ptr].next=head[a];
    edge[ptr].len=len;
    head[a]=ptr++;
    edge[ptr].id=a;
    edge[ptr].next=head[b];
    edge[ptr].len=len;
    head[b]=ptr++;
}
//求所有节点的d[v][0],同时记录最大距离和第二大距离从哪个子节点过来,p是U的父节点,该函数用来求u节点到叶子节点
void fds1(int u,int p)
{
    d[u][0]=0;
    smaxn[u]=0;
    int i;
    for(i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].id;
        if(v==p)    continue;
        fds1(v,u);
        if(smaxn[u]<d[v][0]+edge[i].len)
        {
            smaxn[u]=d[v][0]+edge[i].len;
            smaxnid[u]=v;
            if(smaxn[u]>d[u][0])
            {
                swap(smaxn[u],d[u][0]);
                swap(smaxnid[u],maxnid[u]);
            }
        }
    }
}
//求所有节点的d[v][1],u为v的父节点,p为u的父节点
void fds2(int u,int p)
{
    int i;
    for(i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].id;
        if(v==p)
            continue ;
        if(v!=maxnid[u])
            d[v][1]=edge[i].len+max(d[u][0],d[u][1]);
        else
            d[v][1]=edge[i].len+max(smaxn[u],d[u][1]);
        fds2(v,u);
    }

}
int main()
{
    //freopen("a.txt","r",stdin);
    int n,i,v,len;
    while(scanf("%d",&n)!=EOF)
    {
        init();
        for(i=2;i<=n;i++)
        {
            scanf("%d%d",&v,&len);
            addEdge(i,v,len);
        }
        fds1(1,-1);
        fds2(1,-1);
        for(i=1;i<=n;i++)
            printf("%d\n",max(d[i][0],d[i][1]));
    }

}

树形DP经典题,布布扣,bubuko.com

时间: 2024-12-16 09:00:01

树形DP经典题的相关文章

POJ 1155 TELE 背包型树形DP 经典题

由电视台,中转站,和用户的电视组成的体系刚好是一棵树 n个节点,编号分别为1~n,1是电视台中心,2~n-m是中转站,n-m+1~n是用户,1为root 现在节点1准备转播一场比赛,已知从一个节点传送数据到达另一个节点,电视台需要一定的费用 若可以传送数据到达用户的节点n-m+1~n,这些用户各自愿意支付一定的费用给电视台 现在电视台希望在不亏本的情况下为尽量多的用户转播比赛 输出最多可以为多少用户转播比赛 背包类型的树形DP第一题 dp[i][j]表示以节点i为根的子树有j个用户获得转播,电视

HDU 2196 Computer 树形DP 经典题

给出一棵树,边有权值,求出离每一个节点最远的点的距离 树形DP,经典题 本来这道题是无根树,可以随意选择root, 但是根据输入数据的方式,选择root=1明显可以方便很多. 我们先把边权转化为点权,放在数组cost中 令tree(i)表示以节点i为根的子树 对于节点i,离该节点最远的点要不就是在tree(i)中,要不就是在father(i)上面 令: dp[i][1] : 在子树tree(i)中,离i最远的距离 dp[i][2] : 在子树tree(i)中,离i第二远的距离 (递推的时候需要)

HDU 2196 Computer 树形DP经典题

链接:http://acm.hdu.edu.cn/showproblem.php? pid=2196 题意:每一个电脑都用线连接到了还有一台电脑,连接用的线有一定的长度,最后把全部电脑连成了一棵树,问每台电脑和其它电脑的最远距离是多少. 思路:这是一道树形DP的经典题目.须要两次DFS,第一次DFS找到树上全部的节点在不同子树中的最远距离和次远的距离(在递归中进行动态规划就可以),第二次DFS从根向下更新出终于答案.对于每次更新到的节点u,他的最远距离可能是来自u的子树,或者是u的父亲节点的最远

POJ 1947 Rebuilding Roads (树形dp 经典题)

Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9499   Accepted: 4317 Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The

POJ 2486 Apple Tree (树形dp 经典题)

Apple Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7784   Accepted: 2603 Description Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each node has an amoun

URAL 1018 Binary Apple Tree 树形DP 好题 经典

1018. Binary Apple Tree Time limit: 1.0 secondMemory limit: 64 MB Let's imagine how apple tree looks in binary computer world. You're right, it looks just like a binary tree, i.e. any biparous branch splits up to exactly two new branches. We will enu

POJ 2411 &amp;&amp; HDU 1400 Mondriaan&#39;s Dream (状压dp 经典题)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12341   Accepted: 7204 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

URAL 1039 Anniversary Party 树形DP 水题

1039. Anniversary Party Time limit: 0.5 secondMemory limit: 8 MB Background The president of the Ural State University is going to make an 80'th Anniversary party. The university has a hierarchical structure of employees; that is, the supervisor rela

POJ 3342 树形DP入门题

题目意思和POJ2342一样,只是多加了一个条件,如果最大方案数唯一,输出Yes,不唯一输出No dp的是时候多加一个变量记录答案是否唯一即可 #include "stdio.h" #include "string.h" #include "vector" using namespace std; struct node { int fa; vector<int>child; }data[210]; struct comp { int