【树形DP】 HDU 2196 Computer

题意:求节点间的最大距离

先DFS一次 记录下 每一节点的子树下的最大距离(DP[ u ] [ 0 ])和第二大距离(DP[ u ] [ 1 ])

用DP[ v ] [ 2 ] 表示由v的父节点来的最大距离

再取DP[ u ] [ 0 ] 与 DP[ u ][ 2 ] 的最值

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cmath>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#include <time.h>;
#define cler(arr, val)    memset(arr, val, sizeof(arr))
#define FOR(i,a,b)  for(int i=a;i<=b;i++)
#define IN   freopen ("in.txt" , "r" , stdin);
#define OUT  freopen ("out.txt" , "w" , stdout);
typedef long long  LL;
const int MAXN = 10014;
const int MAXM = 20014;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;
struct node
{
    int v,next;
    LL val;
} edge[MAXM];
int head[MAXM],tol;
LL dp[MAXN][3];
bool vis[MAXN];
void init()
{
    cler(head,-1);
    tol=0;
}
void addedge(int u,int v,LL val)
{
    edge[tol].v=v,edge[tol].val=val,edge[tol].next=head[u];
    head[u]=tol++;
    edge[tol].v=u,edge[tol].val=val,edge[tol].next=head[v];
    head[v]=tol++;
}
void dfs1(int u)
{
    if(vis[u]) return ;
    vis[u]=true;
    for(int i=head[u]; ~i; i=edge[i].next)
    {
        int v=edge[i].v;
        if(!vis[v])
        {
            dfs1(v);
            dp[u][1]=max(dp[u][1],dp[v][0]+edge[i].val);
            if(dp[u][1]>dp[u][0])swap(dp[u][1],dp[u][0]);
        }
    }
}
void dfs2(int u)
{
    if(vis[u]) return ;
    vis[u]=true;
    for(int i=head[u]; ~i; i=edge[i].next)
    {
        int v=edge[i].v,val=edge[i].val;
        if(!vis[v])
        {
            if(dp[u][0]>dp[v][0]+val)//dp[u][0]不是由dp[v][0]+val而来的
                dp[v][2]=max(dp[v][2],max(dp[u][0]+val,dp[u][2]+val));//所以从非v子树来的更长
            else //dp[u][0]由dp[v][0]+val而来的
                dp[v][2]=max(dp[v][2],max(dp[u][1]+val,dp[u][2]+val));//推断非v子树来的哪个长
            dfs2(v);
        }
    }
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int n;
    while(~scanf("%d",&n))
    {
        init();
        for(int i=2; i<=n; i++)
        {
            int a;
            LL b;
            scanf("%d %I64d",&a ,&b );
            addedge(i,a,b);
        }
        cler(vis,false);
        cler(dp,0);
        dfs1(1);
        cler(vis,false);
        dfs2(1);
        for(int i=1;i<=n;i++)
            printf("%I64d\n",max(dp[i][2],dp[i][0]));
    }

}
时间: 2024-10-10 14:42:39

【树形DP】 HDU 2196 Computer的相关文章

树形DP [HDU 2196] Computer

Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3526    Accepted Submission(s): 1788 Problem Description A school bought the first computer some time ago(so this computer's id is 1). D

(树形DP) hdu 2196

Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3982    Accepted Submission(s): 1996 Problem Description A school bought the first computer some time ago(so this computer's id is 1). Du

HDU 2196 Computer 经典树形DP

一开始看错题了,后来发现原来是在一颗带权的树上面求出距离每一个点的最长距离,做两次dfs就好,具体的看注释? #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #incl

fwt优化+树形DP HDU 5909

1 //fwt优化+树形DP HDU 5909 2 //见官方题解 3 // BestCoder Round #88 http://bestcoder.hdu.edu.cn/ 4 5 #include <bits/stdc++.h> 6 // #include <iostream> 7 // #include <cstdio> 8 // #include <cstdlib> 9 // #include <algorithm> 10 // #inc

HDU 2196 Computer 树形DP经典题

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

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

参考来自http://blog.csdn.net/shuangde800/article/details/9732825的思路: 跟思路中不太相同的是,我们如下设置DP数组: dp[i][0] : 表示以i为根的子树中的结点与i的最大距离 dp[i][1] : 表示以i为根的子树中的结点与u的次大距离(即上述思路中的secondDist) dp[i][2] : 表示i往父亲节点方向走的最大距离 同样的,我们也做两次DFS,但是第一次的时候,我们将dp[i][0]和dp[i][1]一起算出来: 第

树形dp/hdu 1011 Starship Troopers

题意 有n个房子,1号为起点房子.每个房子里会消耗一定的士兵来获取一定的价值.现在有m个士兵,求问可以获得的最大价值 注意:走过的房子不能再走 注意2:若要消灭这个房子的bugs,必须全部消灭 分析 典型的树形dp,01背包,因为每个房子里要么全杀死bugs,要么一个不动,只有取或不取两种状态 设f[i][j]表示以i为根节点,消耗j个士兵所能获得的最大价值 则f[i][j]=max(f[son[i]][k] + f[i][j-k]); 答案为f[1][m] Accepted Code 1 /*

HDU 2196 Computer(树形DP求最长路)

Problem Description A school bought the first computer some time ago(so this computer's id is 1). During the recent years the school bought N-1 new computers. Each new computer was connected to one of settled earlier. Managers of school are anxious a

题解报告:hdu 2196 Computer(树形dp)

Problem Description A school bought the first computer some time ago(so this computer's id is 1). During the recent years the school bought N-1 new computers. Each new computer was connected to one of settled earlier. Managers of school are anxious a