题目大意为,求一个树的直径(最长路),以及直径的数量

朴素的dp只能找出某点开始的最长路径,但这个最长路径却不一定是树的直径,本弱先开始就想简单了,一直wa

直到我看了某位大牛的题解。。。

按照那位大牛的思路,我们来考虑直径的构成:

情况1:由某叶子节点出发产生的最长路径直接构成

情况2:由某有多个儿子的节点出发产生的两条长路径组成,这其中,又可以分为两条长路径长度相等与否两种情况

所以 在dp的时候,我们需要记录每个节点出发产生的最长路径和次长路径,以及他们的数量,数量的统计也是非常麻烦

详细请见代码:

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<math.h>
#include<ctype.h>
#include<algorithm>
#include<string>
#include<string.h>
#include<queue>
#define mod 998244353
#define MAX 100000000
using namespace std;
int t,n,m,p,k,tt,f;
int x; int head[];
typedef struct Node
{
int en;
int value;
int next;
}node;
node edge[];
typedef struct DPnode
{
int dp1,dp2,len,nn;
int n1,n2;
}DP;
DP dp[];
void ini()
{
int x,y,z;
for(int i=;i<=n-;i++)
{
scanf("%d%d%d",&x,&y,&k);
edge[*i-].en=y;
edge[*i-].next=head[x];
edge[*i-].value=k;
head[x]=*i-;
edge[*i].en=x;
edge[*i].next=head[y];
edge[*i].value=k;
head[y]=*i;
}
}
void dfs(int s,int p)
{
dp[s].dp1=dp[s].dp2=dp[s].len=dp[s].n1=dp[s].n2=dp[s].nn=;
int leaf=;
for(int i=head[s];i;i=edge[i].next)
{
int q=edge[i].en;
if(q==p)
continue;
leaf=;
dfs(q,s);
int tmp=dp[q].dp1+edge[i].value;
if(tmp>dp[s].dp1)
{
dp[s].dp2=dp[s].dp1;
dp[s].n2=dp[s].n1;
dp[s].dp1=tmp;
dp[s].n1=dp[q].n1;
}
else if(tmp==dp[s].dp1)
{
dp[s].n1+=dp[q].n1;
}
else if(tmp>dp[s].dp2)
{
dp[s].dp2=tmp;
dp[s].n2=dp[q].n1;
}
else if(tmp==dp[s].dp2)
{
dp[s].n2+=dp[q].n1;
}
}
if(leaf)
{
dp[s].n1=;dp[s].nn=;
dp[s].len=;
dp[s].dp1=;
return;
}
int c1=,c2=;
for(int i=head[s];i;i=edge[i].next)
{
int q=edge[i].en;
if(q==p)
continue;
int tmp=dp[q].dp1+edge[i].value;
if(tmp==dp[s].dp1)
c1++;
else if(tmp==dp[s].dp2&&dp[s].dp2)
c2++;
}
if(c1>)
{
dp[s].len=dp[s].dp1*;
int sum=;
for(int i=head[s];i;i=edge[i].next)
{
int q=edge[i].en;
if(q==p)
continue;
if(dp[q].dp1+edge[i].value==dp[s].dp1)
{
dp[s].nn+=sum*dp[q].n1;
sum+=dp[q].n1;
}
}
}
else if(c2>)
{
dp[s].len=dp[s].dp1+dp[s].dp2;
for(int i=head[s];i;i=edge[i].next)
{
int q=edge[i].en;
if(q==p)
continue;
if(dp[q].dp1+edge[i].value==dp[s].dp2)
{
dp[s].nn+=dp[s].n1*dp[q].n1;
}
}
}
else
{
dp[s].len=dp[s].dp1;
dp[s].nn=dp[s].n1;
}
return ;
}
void solve()
{
int ans=;
int num=;
for(int i=;i<=n;i++)
{
if(dp[i].len>ans)
{
ans=dp[i].len;
num=dp[i].nn;
}
else if(dp[i].len==ans)
{
num+=dp[i].nn;
}
}
printf("%d %d\n",ans,num);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(head,,sizeof(head));
ini();
dfs(,);
solve();
}
return ;
}

hdu3534,个人认为很经典的树形dp的更多相关文章

  1. hdu 1011 Starship Troopers 经典的树形DP ****

    Starship Troopers Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  2. ZOJ2599:Graduated Lexicographical Ordering(很经典的数位DP)

    Consider integer numbers from 1 to n. Let us call the sum of digits of an integer number its weight. ...

  3. POJ1947 - Rebuilding Roads(树形DP)

    题目大意 给定一棵n个结点的树,问最少需要删除多少条边使得某棵子树的结点个数为p 题解 很经典的树形DP~~~直接上方程吧 dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v] ...

  4. SGU 149. Computer Network( 树形dp )

    题目大意:给N个点,求每个点的与其他点距离最大值 很经典的树形dp...很久前就想写来着...看了陈老师的code才会的...mx[x][0], mx[x][1]分别表示x点子树里最长的2个距离, d ...

  5. HDU 5834 Magic boy Bi Luo with his excited tree(树形dp)

    http://acm.hdu.edu.cn/showproblem.php?pid=5834 题意: 一棵树上每个节点有一个价值$Vi$,每个节点只能获得一次,每走一次一条边要花费$Ci$,问从各个节 ...

  6. 【树形DP】洛谷P1352_没有上司的舞会

    本人第一篇Blog,初学树形DP,心情别样鸡冻... 好了废话不多说,我们来看看题目[传送门] 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是 ...

  7. HDU 1561 The more, The Better 经典树形DP

    The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  8. 洛谷 P1352 没有上司的舞会【树形DP】(经典)

    <题目链接> <转载于>>> > 题目描述: 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的 ...

  9. 蓝桥杯 算法提高 金属采集 [ 树形dp 经典 ]

    传送门 算法提高 金属采集 时间限制:1.0s   内存限制:256.0MB     锦囊1   锦囊2   锦囊3   问题描述 人类在火星上发现了一种新的金属!这些金属分布在一些奇怪的地方,不妨叫 ...

随机推荐

  1. Java基础知识强化85:System类之arraycopy()方法(数组拷贝)

    1. arraycopy方法(数组拷贝) public static void arraycopy(object src,int srcPos,Object dest,int destPos, int ...

  2. ajax的来龙去脉

    这是我在博客园写的第一遍博客,之前都是只看不写,在园子里学到了不少的东西,现在也想着把自己的一些感悟写出来给大家分享一下. ajax技术可以说是Web2.0应用程序的技术基础,尽管软件经销商和开源社区 ...

  3. sass笔记-4|像写脚本一样写Sass,把能交给Sass办的都交给它

    Sass笔记关于sass的基础部分已经写完,这一篇介绍Sass的高级特性--脚本特性.Sass能做很多事让样式表更智能,我们先会看到Sass眼中的数据类型,在这些数据类型上会有可进行的操作,此外,Sa ...

  4. machine learning in action , part 1

    We should think in below four questions: the decription of machine learning key tasks in machine lea ...

  5. Swift中面向协议的编程

    什么是面向协议的编程? 面向协议的编程,是一种编程范式. 编程范式,是一个计算机科学用语.维基百科中的解释是,计算机编程的基本风格或典型模式.通俗来说,就是解决某一个问题的方法不同方法和思路. 像大家 ...

  6. Python迭代--笔记

    <python3 程序开发指南> 迭代子.迭代操作 迭代子是一个对象,该对象可提供_next_()方法,该方法依次返回每个相继的数据项,并在没有数据项时产生StopIteration()异 ...

  7. ExecuteNonQuary接收存储过程的输出类型的变量的值

    1.设置所调用的存储过程需要的参数 public decimal CreateOrder(string orderId, int userId, string address) { SqlParame ...

  8. MySQL TEXT数据类型的最大长度

    TINYTEXT 256 bytes   TEXT 65,535 bytes ~64kb MEDIUMTEXT  16,777,215 bytes ~16MB LONGTEXT 4,294,967,2 ...

  9. Winamp传统外观皮肤MusicRio发放

    这款皮肤是我在2002年自己弄的,如果能给还在使用Winamp的朋友使用那就最好了. 下载地址:http://files.cnblogs.com/lzhdim/MusicRio.rar

  10. iOS8中添加的extensions总结(二)——分享扩展

    分享扩展 注:此教程来源于http://www.raywenderlich.com的<iOS8 by Tutorials> 1.准备 这次例子来源于国外的图片分享网站Imgur.com 首 ...