hdu3534,个人认为很经典的树形dp
题目大意为,求一个树的直径(最长路),以及直径的数量
朴素的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的更多相关文章
- hdu 1011 Starship Troopers 经典的树形DP ****
Starship Troopers Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
- 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. ...
- POJ1947 - Rebuilding Roads(树形DP)
题目大意 给定一棵n个结点的树,问最少需要删除多少条边使得某棵子树的结点个数为p 题解 很经典的树形DP~~~直接上方程吧 dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v] ...
- SGU 149. Computer Network( 树形dp )
题目大意:给N个点,求每个点的与其他点距离最大值 很经典的树形dp...很久前就想写来着...看了陈老师的code才会的...mx[x][0], mx[x][1]分别表示x点子树里最长的2个距离, d ...
- HDU 5834 Magic boy Bi Luo with his excited tree(树形dp)
http://acm.hdu.edu.cn/showproblem.php?pid=5834 题意: 一棵树上每个节点有一个价值$Vi$,每个节点只能获得一次,每走一次一条边要花费$Ci$,问从各个节 ...
- 【树形DP】洛谷P1352_没有上司的舞会
本人第一篇Blog,初学树形DP,心情别样鸡冻... 好了废话不多说,我们来看看题目[传送门] 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是 ...
- 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 ...
- 洛谷 P1352 没有上司的舞会【树形DP】(经典)
<题目链接> <转载于>>> > 题目描述: 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的 ...
- 蓝桥杯 算法提高 金属采集 [ 树形dp 经典 ]
传送门 算法提高 金属采集 时间限制:1.0s 内存限制:256.0MB 锦囊1 锦囊2 锦囊3 问题描述 人类在火星上发现了一种新的金属!这些金属分布在一些奇怪的地方,不妨叫 ...
随机推荐
- android 使用String.format("%.2f",67.876)自已定义语言(俄语、西班牙语)会把小数点变为逗号
市场人员反映公司的app使用系统设置俄语.西班牙语,double数据会把小数点变为逗号.调试一下,是自定义的语言时候(例如,俄语.西班牙语)转换String.format("%.2f&quo ...
- android listview综合使用演示样例_结合数据库操作和listitem单击长按等事件处理
本演示样例说明: 1.自己定义listview条目样式,自己定义listview显示列数的多少,灵活与数据库中字段绑定. 2.实现对DB的增删改查,而且操作后listview自己主动刷新. 3.响应用 ...
- String,StringBuffer与StringBuilder的差别??
String 字符串常量StringBuffer 字符串变量(线程安全)StringBuilder 字符串变量(非线程安全) 简要的说, String 类型和 StringBuffer 类型的主要性能 ...
- hdu 5062
题意:将10^0-10^6之间属于 "Beautiful Palindrome Number" 的数个数打印出来,所谓 "Beautiful Palindrome Nu ...
- setTimeout()与setInterval()方法区别介绍
计时器setTimeout()和setInterval()两个都是js的计时功能的函数两个有些区别,下面为大家简单介绍下,希望对大家有所帮助 计时器setTimeout()和setInterval ...
- maven第四章背景案例
4.3简要设计 4.3.1接口设计 4.3.2模块结构 思想 先定义出核心接口,一个接口可以认为是一个功能,根据接口划分功能 设计模式就是一种思想,外观模式和代理模式,适配者模式三者的区别 http: ...
- dsoframer组件详细使用(aspx.net)
近来由于工作需要,要求实现一个office文档在线编辑器 关于在线操作office 我是一点经验没有 网上查了半天资料 锁定了一款组件(ActiveX控件dsoframer,一个用C++实现的offi ...
- Android NDK编程,引入第三方.so库
android自带的编译工具NDK进行编译时(非单纯的调用第三方.so而是进行ndk编程),armeabi以及armeabi-v7a文件夹下的第三方so文件将会被删除,只会产生编译后的so文件,其他的 ...
- 通过安全策略限制局域网部分IP访问我的电脑
一旦电脑连上局域网,那么别人就容易进入自己的电脑,造成隐私被泄漏,这是我们最不愿发生的情况.因此,如果你的电脑并不需要向局域网其他用户共享资料,那么就建议采用策略,禁止局域网电脑访问自己的电脑,以保证 ...
- Knockoutjs官网翻译系列(二) Observable 数组
承接前文,前文书说道了KO框架中如何使用observable的视图模型属性来与UI元素进行绑定并自动进行双向更新的事儿.observable属性除了服务基础数据类型之外,还定义了专门为服务数组类型的o ...