HDU 2196(树形dp

题目:求出一棵树上的所有点到其他点的最长距离。

思路:取一个根节点进行dfs,先求出每个节点到子节点的最长路和次长路(也就是与最长路不同的最长的路,有可能与最长路长度相等),并记录最长路和次长路通过的相邻节点的标号。然后进行第二次dfs,考虑最长路是通过父节点的情况,如果该节点v在父节点的最长路上,那么需要取次长路,否则就取最长路。

第二次dfs的时候最长路的通过节点还是要更新,因为若某个父节点的最长路是朝祖先走的,那么其子节点的最长路一定朝祖先走,且与v是否在父节点向下的最长路上无关。

#include<iostream>
#include<map>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<queue>
#include<stack>
#include<functional>
#include<set>
#include<cmath>
#define pb push_back
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps 0.0000000001
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
const int maxv=1e4+300;
int N;
vector<P> G[maxv];
int maxd[maxv],maxdn[maxv],smaxd[maxv],smaxdn[maxv];
void dfs1(int u,int f){
    maxd[u]=smaxd[u]=0;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fs;
        int len=G[u][i].se;
        if(v==f) continue;
        dfs1(v,u);
        if(len+maxd[v]>smaxd[u]){
            smaxd[u]=len+maxd[v];
            smaxdn[u]=v;
        }
        if(smaxd[u]>maxd[u]){
            swap(smaxd[u],maxd[u]);
            swap(smaxdn[u],maxdn[u]);
        }
    }
}
void dfs2(int u,int f){
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fs;
        int len=G[u][i].se;
        if(v==f) continue;
        if(maxdn[u]==v){
            if(smaxd[u]+len>smaxd[v]){
                smaxd[v]=smaxd[u]+len;
                smaxdn[v]=u;
            }
            if(smaxd[v]>maxd[v]){
                swap(maxd[v],smaxd[v]);
                swap(maxdn[v],smaxdn[v]);
            }
        }else{
            if(maxd[u]+len>smaxd[v]){
                smaxd[v]=maxd[u]+len;
                smaxdn[v]=u;
            }
            if(smaxd[v]>maxd[v]){
                swap(maxd[v],smaxd[v]);
                swap(maxdn[v],smaxdn[v]);
            }
        }
        dfs2(v,u);
    }
}
int main(){
    /////freopen("/home/files/CppFiles/in","r",stdin);
    /*    std::ios::sync_with_stdio(false);
        std::cin.tie(0);*/
    while(cin>>N){
        for(int i=1;i<=N;i++) G[i].clear();
        for(int i=2;i<=N;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            G[i].pb(P(a,b));
            G[a].pb(P(i,b));
        }
        dfs1(1,-1);
        dfs2(1,-1);
        for(int i=1;i<=N;i++){
            printf("%d\n",maxd[i]);
        }
    }
    return 0;
}

时间: 2024-10-02 05:57:25

HDU 2196(树形dp的相关文章

hdu 2196 树形dp

题意: 给你n太台电脑 及 相邻之间的 距离 让你求出 每台电脑的离它最远的电脑的离: 思路:树形dp,题意给出一棵树,求离每个节点最远的点的距离, 两种情况1,以该节点s作为根节点的子树中的离该节点最长距离x.2,其父树中离该节点的最长距离y.答案就是max(x, y); 需要注意的是:父树中的最长距离有可能经过s点, 这时候就要选父树中次长的路径(求第一种时顺便求出) ps:建图时是双向边  不明白在纸上画图走一遍样例 代码: #include <iostream> #include &l

Computer HDU - 2196(树形dp)

题目要求:求树上每个点能到达的最远距离 dp[u][0]:u的子树下u的最远距离是多少 dp[u][1]:u的子树次远距离是多少 dp[u][2]:u的父亲能走的最远距离是多少 dp[0] [1]dfs处理即可 如果vi不是u最长距离经过的节点,f[vi][1] = dist(vi,u)+max(f[u][0], f[u][1]) 如果vi是u最长距离经过的节点,那么不能选择f[u][0],因为这保存的就是最长距离,要选择u次大距离 #include<bits/stdc++.h> #defin

hdu 4123 树形DP+RMQ

http://acm.hdu.edu.cn/showproblem.php?pid=4123 Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the route. There are N houses and N - 1 roads in his village. Each road connects two houses,

hdu 1250 树形DP

Anniversary party Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Appoint description:  System Crawler  (2014-07-27) Description There is going to be a party to celebrate the 80-th Anniversary of the Ural St

hdu 4276(树形dp)

题意:带权树上有起点终点每个点上有宝藏,一个人只有T分钟要从起点到重点,问你最多能收集多少宝藏. 思路:树形dp,首先判断能不能走到终点,然后把路径上的边权变为0时间减去所有边权.dp[v][j]表示从v出发回到v话费j分钟最多能收集到的宝藏. dp[v][j] = max(dp[v][j], dp[x][k] + dp[v][j-k-2*val]); 被G++卡了好长时间,换成c++就过了. 代码如下: 1 #include <stdio.h> 2 #include <string.h

hdu 5148 树形dp+分组背包问题

http://acm.hdu.edu.cn/showproblem.php?pid=5148 Problem Description Long long ago,there is a knight called JayYe.He lives in a small country.This country is made up of n cities connected by n-1 roads(that means it's a tree).The king wants to reward Ja

HDU 1520 树形dp裸题

1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define max(a,b) a>b?a:b using nam

hdu 3586 树形dp+二分

题目大意:给定n个敌方据点,1为司令部,其他点各有一条边相连构成一棵 树,每条边都有一个权值cost表示破坏这条边的费用,叶子节点为前线.现要切断前线和司令部的联系,每次切断边的费用不能超过上限limit,问切断所 有前线与司令部联系所花费的总费用少于m时的最小limit.1<=n<=1000,1<=m<=100万 题目要问的是最小的最大限制,必然二分答案 然后对于每一个值,树形DP判定是否可行 dp[i]表示要切断以i为根的其它所有子树的最小代价. 其中设定叶子结点的代价为无穷大

HDU 1561 树形DP入门

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6011    Accepted Submission(s): 3555 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物

hdu 1561 树形dp

又一道树形dp,发现其实树形dp长得都挺像的. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int INF = -9999999; 7 const int N = 201; 8 int dp[N][N]; 9 int head[N]; 10 int value[N]; 11 int n, m, e; 12 13 void i