HDU2196[树形dp+二次扫描]java和c++版本题解

题目大意:就是给你一颗树,问你从每个点出发能到达的最远距离是多少,第一行输入点的个数 n n n,第 n − 1 n-1 n1行是输入两个数 x , y x,y x,y,一个是第 i i i行是第 i i i个点连接上 x x x,距离是 y y y


解题思路:很明显从每个点出发到达最远的距离这是一个无根树,那么我们应该先把无根树转成有根树,那么对于一个点 a i a_i ai它答案有两种:1向子节点走2向父节点走
1.第一遍dfs,我们求每个点向其子节点走的时候能到达的最远距离Maxdiat[i];
2。第二遍dfs,我们求出每个点向其父节点走的最远距离的,那么我们知道有可能这个点的父节点的最远距离的路径是走通过这个点的,那么我们用父节点的次长路径去更新,【记得每次dfs都要不断跟新次长路径】


C++;

#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1) 
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define next Next
#define count Count
#define pb push_back
#define f first
#define s second
using namespace std;
const int N = 1e5+10, mod = 1e9 + 7;
const double eps = 1e-10;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
template<typename T> void read(T &x)
{
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) 
{
    read(first);
    read(args...);
}
int T;
struct node 
{
    int to, next, dist;
}e[N];
int head[N], cnt;
int Maxdist[N], Maxdist2[N];
inline void add(int from,  int to, int dist)
{
    e[cnt] = {to,head[from],dist};
    head[from] = cnt ++;
}

void dfs1(int u,int fa)
{ 
    Maxdist[u] = 0;
    Maxdist2[u] = 0;
    for(int i = head[u]; ~i ; i = e[i].next)
    {
        int v = e[i].to;
        if(v == fa) continue;
        dfs1(v,u);
        if(Maxdist[u] <= Maxdist[v] + e[i].dist)
        {
            Maxdist2[u] = Maxdist[u];
            Maxdist[u] = Maxdist[v] + e[i].dist;
        }
        else if(Maxdist[v] + e[i].dist > Maxdist2[u])
            Maxdist2[u] = Maxdist[v] + e[i].dist;
    }
}

void dfs2(int u, int fa, int len)
{
    if(Maxdist[fa] != Maxdist[u] + len)
    {
        if(Maxdist[fa]+len >= Maxdist[u])
        {
            Maxdist2[u] = Maxdist[u];
            Maxdist[u] = Maxdist[fa]+len;
        }
        else if(Maxdist[fa]+len > Maxdist2[u])
         Maxdist2[u] = Maxdist[fa]+len;
    }
    else 
    {
        if(Maxdist2[fa]+len >= Maxdist[u])
        {
            Maxdist2[u] = Maxdist[u];
            Maxdist[u] = Maxdist2[fa]+len;
        }
        else if(Maxdist2[fa]+len > Maxdist2[u])
         Maxdist2[u] = Maxdist2[fa]+len;
    }
    
    for(int i = head[u]; ~i; i = e[i].next)
    {
        int v = e[i].to;
        if(v == fa) continue;
        dfs2(v,u,e[i].dist);
    }
}

int main()
{
   
    while(scanf("%d",&T)!=EOF)
    {
        ms(head,-1), cnt = 0;
        for(int i = 2; i <= T; ++ i)
        {
            int l, dist;
            read(l,dist);
            add(i,l,dist);
            add(l,i,dist);
        }
        dfs1(1,0);
        // for(int i = 1; i <= T; ++ i)
        //  printf("%d %d\n",Maxdist[i],Maxdist2[i]);
        //  cout << endl;
        for(int i = head[1]; ~i; i = e[i].next)
        dfs2(e[i].to,1,e[i].dist);
        for(int i = 1; i <= T; ++ i)
         printf("%d\n",Maxdist[i]);
    }
    return 0;
}



JAVA

package test2;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.math.BigInteger;
class node 
{
	public int to, next, dist;
	public node(int x, int y, int z)
	{
		to = x;
		next = y;
		dist = z;
	}
}
public class Main 
{
   static int head[] = new int [100010];
   static int Maxdist[] = new int [100010];
   static int Maxdist2[] = new int [100010];
   static node e[] = new node[100010];
   static int cnt = 0;
   
   static void add(int from, int to, int dist)
   {
	   e[cnt] = new node(to,head[from],dist);
	   head[from] = cnt ++;
   }
   
   static void dfs1(int u,int fa)
   { 
       Maxdist[u] = 0;
       Maxdist2[u] = 0;
       for(int i = head[u]; i != -1 ; i = e[i].next)
       {
           int v = e[i].to;
           if(v == fa) continue;
           dfs1(v,u);
           if(Maxdist[u] <= Maxdist[v] + e[i].dist)
           {
               Maxdist2[u] = Maxdist[u];
               Maxdist[u] = Maxdist[v] + e[i].dist;
           }
           else if(Maxdist[v] + e[i].dist > Maxdist2[u])
               Maxdist2[u] = Maxdist[v] + e[i].dist;
       }
   }
   
   static void dfs2(int u, int fa, int len)
   {
       if(Maxdist[fa] != Maxdist[u] + len)
       {
           if(Maxdist[fa]+len >= Maxdist[u])
           {
               Maxdist2[u] = Maxdist[u];
               Maxdist[u] = Maxdist[fa]+len;
           }
           else if(Maxdist[fa]+len > Maxdist2[u])
            Maxdist2[u] = Maxdist[fa]+len;
       }
       else 
       {
           if(Maxdist2[fa]+len >= Maxdist[u])
           {
               Maxdist2[u] = Maxdist[u];
               Maxdist[u] = Maxdist2[fa]+len;
           }
           else if(Maxdist2[fa]+len > Maxdist2[u])
            Maxdist2[u] = Maxdist2[fa]+len;
       }
       
       for(int i = head[u]; i != -1; i = e[i].next)
       {
           int v = e[i].to;
           if(v == fa) continue;
           dfs2(v,u,e[i].dist);
       }
   }

   
   public static void main(String [] args)
   {
	   Scanner s = new Scanner(System.in);
	   
	   while(s.hasNext())
	   {
		   int T = s.nextInt();
		   cnt = 0;
		   for(int i = 0; i < 100010; ++ i)
			   head[i] = -1;
		   for(int i = 2; i <= T; ++ i)
		   {
			   int r = s.nextInt();
			   int dist = s.nextInt();
			   add(i,r,dist);
			   add(r,i,dist);
		   }
		   dfs1(1,0);
	        for(int i = head[1]; i != -1; i = e[i].next)
	        dfs2(e[i].to,1,e[i].dist);
	       for(int i = 1; i <= T; ++ i)
	         System.out.println(Maxdist[i]);
	 
	   }
   }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值