HDU3534(SummerTrainingDay13-C tree dp)

本文介绍了一种算法,用于解决如何找到给定树中节点间的最长路径及其出现次数的问题。通过使用深度优先搜索(DFS)和动态规划的思想,文章提供了一个具体的实现方案,并附带了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1574    Accepted Submission(s): 511


Problem Description

In the Data structure class of HEU, the teacher asks one problem: How to find the longest path of one tree and the number of such longest path?
 

 

Input

There are several test cases. The first line of each case contains only one integer N, means there are N nodes in the tree. N-1 lines follow, each line has three integers w,v and len, indicate that there is one edge between node w and v., and the length of the edge is len.

 

 

Output

For each test case, output the length of longest path and its number in one line.
 

 

Sample Input

4 1 2 100 2 3 50 2 4 50 4 1 2 100 2 3 50 3 4 50
 

 

Sample Output

150 2 200 1
 

 

Source

 

//2017-08-16
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1000010;
const int INF = 0x3f3f3f3f;

//链式前向星存图
int head[N], tot;
struct Edge{
    int to, next, w;

}edge[N<<2];

void add_edge(int u, int v, int w){
    edge[tot].w = w;
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}

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

//dp[u]记录以u为根的子树,过u往下的最长路径。
//cnt[u]记录子树u上最长路径的数目。
int dp[N], cnt[N], ans, num;

void dfs(int u, int fa){
    dp[u] = 0;
    cnt[u] = 1;
    for(int i = head[u]; i != -1; i = edge[i].next){
        int v = edge[i].to;
        int w = edge[i].w;
        if(v == fa)continue;
        dfs(v, u);
        if(dp[u]+dp[v]+w > ans){
            ans = dp[u]+dp[v]+w;
            num = cnt[u]*cnt[v];
        }else if(dp[u]+dp[v]+w == ans)
              num += cnt[u]*cnt[v];
        if(dp[u] < dp[v]+w){
            dp[u] = dp[v]+w;
            cnt[u] = cnt[v];
        }else if(dp[u] == dp[v]+w)
              cnt[u] += cnt[v];
    }
}

int main()
{
    //freopen("input.txt", "r", stdin);
    int n;
    while(scanf("%d", &n)!=EOF){
        int u, v, w;
        init();
        for(int i = 0; i < n-1; i++){
            scanf("%d%d%d", &u, &v, &w);
            add_edge(u, v, w);
            add_edge(v, u, w);

        }
        ans = -INF;
        num = 0;
        dfs(1, 0);
        printf("%d %d\n", ans, num);
    }

    return 0;

}

 

转载于:https://www.cnblogs.com/Penn000/p/7375346.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值