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 问题描述 人类在火星上发现了一种新的金属!这些金属分布在一些奇怪的地方,不妨叫 ...
随机推荐
- C++库研究笔记——Linux下是否需要使用memory pool?
Linux Slab分配器(一)--概述 Linux slab 分配器剖析 C++库研究笔记——内存池实现 做了一些测试:发现linux使用内存池与否没有明显差别,仅仅有2倍. Linux内存处理机制 ...
- Spark Streaming与kafka整合实践之WordCount
本次实践使用kafka console作为消息的生产者,Spark Streaming作为消息的消费者,具体实践代码如下 首先启动kafka server .\bin\windows\kafka-se ...
- 常用git命令整理
花了一点时间来熟悉和整理git常用命令. 推荐的git学习资料:1.搜“Git Community Book 中文版.pdf”,git社区书,内容全面且简明扼要,第一推荐2.搜“Git权威指南.pdf ...
- N皇后问题--递归回溯
著名的N皇后问题,就是先按照行一行一行的找,先找第一行,第一行找到一列能满足条件,继续找下一行,如果下一行也找到一列能满足条件,继续找下一行,一次类推,最终找到解, 但是,如果找不到的话, 就说明上一 ...
- html:标签原本属性
<!doctype html>无标题文档 a标签,默认有text-decoration属性 span标签不需要清零 b标签不需要清零 em标签不需要清零 strong 相邻内嵌元素代码里面 ...
- toString结果
String[] str = new String[] { "a", "b", "c" }; System.out.println(str) ...
- MySQL查看数据库大小、表大小和最后修改时间
查看数据库表基本信息. select * from information_schema.TABLES where information_schema.TABLES.TABLE_SCHEMA = ' ...
- rtsp转发服务器设计
做一个设备实时监控.需求是这样的,一个用户有多个设备(android系统,支持摄像头),设备分布在家中或者其它地方:用户可以远程通过终端(手机.pc.ipad,etc...)管理操纵这些设备(包括实时 ...
- iOS9中请求出现App Transport Security has blocked a cleartext HTTP (http://)
错误描述: App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecu ...
- [转] linux 下 进程和线程的区别
1.进程与线程 进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程的一个执行流,是C ...