树形DP(统计直径的条数 HDU3534)
分析:首先树形dp(dfs计算出每个点为根节点的子树的最长距离和次长距离),然后找出L=dis[u][0]+dis[u][1]最长的那个点u,然后在以u为根节点dfs,统计长度为L的条数:具体做法:把u的儿子节点为根节点的子树深搜遍历到每个叶子节点,用h[dist[v]]统计该子树中u到v的距离,然后对于遍历过的叶子节点且不再当前子树中的s[L-dist[v]]的个数加到ans中,最后ans即为所求条数:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"queue"
#include"algorithm"
#include"string.h"
#include"string"
#include"math.h"
#include"vector"
#include"stack"
#include"map"
#define eps 1e-4
#define inf 0x3f3f3f3f
#define M 100009
#define PI acos(-1.0)
using namespace std;
struct node
{
int u,v,next;
__int64 w;
}edge[M*2];
int t,head[M],belong[M],dis[M][4],degree[M];
int cnt;
__int64 dist[M],a[M],L,ans;
map<__int64,int>s,h;
void init()
{
t=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
edge[t].u=u;
edge[t].v=v;
edge[t].w=w;
edge[t].next=head[u];
head[u]=t++;
}
void dfs(int u,int f)
{
dis[u][0]=0;
dis[u][1]=0;
for(int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].v;
if(v==f)continue;
dfs(v,u);
if(dis[u][0]<dis[v][0]+edge[i].w)
{
dis[u][1]=dis[u][0];
dis[u][0]=dis[v][0]+edge[i].w;
}
else if(dis[u][1]<dis[v][0]+edge[i].w)
dis[u][1]=dis[v][0]+edge[i].w;
}
}
void dfs2(int u,int f);
void dfs1(int u,int f)
{
s.clear();
for(int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].v;
if(v==f)continue;
h.clear();
dist[v]=edge[i].w;
cnt=0;
dfs2(v,u);
for(int j=0;j<cnt;j++)
{
s[a[j]]+=h[a[j]];
}
}
}
void dfs2(int u,int f)
{
if(degree[u]==1)
{ if(h[dist[u]]==0)
a[cnt++]=dist[u];
h[dist[u]]++;
if(s[L-dist[u]])
{
ans+=s[L-dist[u]];
//printf("%d %d\n",s[L-dist[u]],h[dist[u]]);
}
}
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==f)continue;
dist[v]=dist[u]+edge[i].w;
dfs2(v,u);
}
}
int main()
{
int n,i,a,b;
__int64 c;
while(scanf("%d",&n)!=-1)
{
init();
memset(degree,0,sizeof(degree));
for(i=1;i<n;i++)
{
scanf("%d%d%I64d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
degree[a]++;
degree[b]++;
}
if(n==1)
{
printf("0 1\n");
continue;
}
if(n==2)
{
printf("%I64d 1\n",edge[0].w);
continue;
}
for(i=1;i<=n;i++)
{
if(degree[i]>1)
{
dfs(i,-1);
break;
}
}
int id=1;
L=dis[id][0]+dis[id][1];
for(i=2;i<=n;i++)
{
if(dis[id][0]+dis[id][1]<dis[i][0]+dis[i][1])
{
L=dis[i][0]+dis[i][1];
id=i;
}
}
ans=0;
dfs1(id,-1);
printf("%I64d %I64d\n",L,ans);
}
}
树形DP(统计直径的条数 HDU3534)的更多相关文章
- hdoj3534(树形dp,求树的直径的条数)
题目链接:https://vjudge.net/problem/HDU-3534 题意:给出一棵树,求树上最长距离(直径),以及这样的距离的条数. 思路:如果只求直径,用两次dfs即可.但是现在要求最 ...
- 树形DP 统计树中长度为K的路径数量——Distance in Tree
一.问题描述 给出一棵n个节点的树,统计树中长度为k的路径的条数(1<=n<=50000 , 1<=k<=500). 二.解题思路 设d[i][k]表示以i为根节点长度为k的路 ...
- bzoj1912 树形dp求直径(新写法),求直径的两端点
通过回溯法可以求出直径的两个端点,同时注意有负权边的树求直径不可以用两次dfs来求,而必须用dp做 /* 分情况讨论问题 一条边也不加的情况,显然每条边要扫描两次, 该情况的答案是2(n-1) 只加一 ...
- tarjan算法求缩点+树形DP求直径
hdu4612 Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) ...
- mysql根据分组和条件查询以后如何统计记录的条数
1.子查询,查询出的数据随便起一个别名,然后根据分组和条件查询出的数据,作为一个具有一列的一个表,然后外面的查询查询这个数据表的这一列的总数,即可. SELECT COUNT( * ) FROM ( ...
- Luogu4630 APIO2018 Duathlon 圆方树、树形DP
传送门 要求的是一条按顺序经过\(s,t,c\)三个点的简单路径.简单路径的计数问题不难想到点双联通分量,进而使用圆方树进行求解. 首先将原图缩点,对于一个大小为\(size\)的点双联通分量内,在这 ...
- 洛谷 P2986 [USACO10MAR]Great Cow Gat…(树形dp+容斥原理)
P2986 [USACO10MAR]伟大的奶牛聚集Great Cow Gat… 题目描述 Bessie is planning the annual Great Cow Gathering for c ...
- Codeforces 919D Substring (拓扑排序+树形dp)
题目:Substring 题意:给你一个有向图, 一共有n个节点 , m条变, 一条路上的价值为这个路上出现过的某个字符最多出现次数, 现求这个最大价值, 如果价值可以无限大就输出-1. 题解:当这个 ...
- HDU2242 考研路茫茫——空调教室 (双联通分+树形DP)
考研路茫茫——空调教室 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
随机推荐
- SQL Server 触发器【转】
触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程.触发器主要是通过事件进行触发被自动调用执行的.而存储过程可以通过存储过程的名称被调用. Ø 什么是触发器 触发器对表进行插入.更新.删 ...
- 处理PHP字符串的10个简单方法;mysql出现乱码:character_set_server=utf8
PHP处理字符串的能力非常强大,方法也是多种多样,但有的时候你需要选择一种最简单且理想的解决方法.文章列举了10个PHP中常见的字符串处理案例,并提供了相对应的最理想的处理方法. 1.确定一个字符串的 ...
- su terminal get around---docker root
su : must be run from a terminal After some googling, I found the solution from Tero's glob. If you ...
- mvc EF 数据保存时,报错:”对一个或多个实体的验证失败……“之解决
在EF5.0添加实体数据到数据库的时候,出现“对一个或多个实体的验证失败.有关详细信息,请参见“EntityValidationErrors”属性这个错误 解决: SaveChanges前先关闭验证实 ...
- zepto-创建dom
在使用zepto时,为了使得ajax请求回来的数据添加到页面上之后,不至于失去所绑定的事件. 我一般会采用$()创建dom元素节点,然后添加所需要的class和html等等一系列的样式,最基本的是$( ...
- 单个未知大小图片在div里面垂直居中的方法。。。添加辅助元素挤一下位置达到居中
单个未知大小图片在div里面垂直居中的方法...添加辅助元素挤一下位置达到居中 <div class="ServicesLiTopPic"> <i>&l ...
- SQL 2008 RAISERROR语法在SQL 2012/2014不兼容问题
原文 旧的RAISERROR语法在SQL 2012不兼容问题 raiserror 写法: SQL 2008: raiserror 55030 'text error' SQL 2012: raiser ...
- linux pipe
1. 函数说明 pipe(建立管道): 1) 头文件 #include<unistd.h> 2) 定义函数: int pipe(int filedes[2]); 3) 函数说明: pipe ...
- 【C++】利用指针实现通过函数改变多个参数的值
写惯了python,对于C++的语法越来越生疏,不同于python中函数可以return多个变量,C++的函数要想返回多个参数可以利用指针实现. 因为在函数内部的变量都是局部变量,所以当参数传入函数中 ...
- SQL Server 2008 R2,显示SQL语句执行窗口。 编辑前200行,可以执行SQL语句