bzoj1912 树形dp求直径(新写法),求直径的两端点
通过回溯法可以求出直径的两个端点,同时注意有负权边的树求直径不可以用两次dfs来求,而必须用dp做
/*
分情况讨论问题
一条边也不加的情况,显然每条边要扫描两次,
该情况的答案是2(n-1)
只加一条边的情况,找到直径,将其变成一个环,在这个环上的所有边只要扫描一次,剩下的边就要扫描两次
设直径为L,该情况下的答案是 2(n-1-L)+L+1=2n-L-1=2(n-1)-(L-1)
加两条边的情况,在加入第一条边出现环的情况下,再加入一条边形成的环会和原来的环有重合
重合的部分任然要扫描两次,所以新加入的边要使形成的环和原来的环非重合的边和重合的边的差最大
那么如何快速求新加入的边?只要将第一条边加入后形成的环的边权值变成-1,然后再求一次直径即可
设第一次的直径L1,第二次的直径L2,那么该情况下的答案是2(n-1)-(L1-1)-(L2-1)
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
struct Edge{int to,nxt,w;}edge[maxn<<];
int head[maxn],tot,n,k,ans;
void init(){
memset(head,-,sizeof head);
tot=;
}
void addedge(int u,int v){
edge[tot].w=;edge[tot].to=v;edge[tot].nxt=head[u];head[u]=tot++;
} int pre1[maxn],pre2[maxn],dp[maxn],mx;//记录x的最长和次长子链的边的下标
int dfs(int x,int fa)
{
int mx1=,mx2=;
for(int i=head[x];i!=-;i=edge[i].nxt)
if(edge[i].to!=fa)
{
int v=edge[i].w+dfs(edge[i].to,x);
if(v>mx1)mx2=mx1,mx1=v,pre2[x]=pre1[x],pre1[x]=i;
else if(v>mx2)mx2=v,pre2[x]=i;
}
if(mx1+mx2>ans)ans=mx1+mx2,mx=x;
return mx1;
} int main(){
init();
memset(pre1,-,sizeof pre1);
memset(pre2,-,sizeof pre2);
cin>>n>>k;
int tot=*n-;
for(int i=;i<n;i++){
int u,v;cin>>u>>v;
addedge(u,v);addedge(v,u);
}
dfs(,);
tot=tot-ans+;
if(k==)
{
ans=;
for(int i=pre1[mx];i!=-;i=pre1[edge[i].to])edge[i].w=edge[i^].w=-;
for(int i=pre2[mx];i!=-;i=pre1[edge[i].to])edge[i].w=edge[i^].w=-;
dfs(,);tot=tot-ans+;
}
cout<<tot<<endl;
}
bzoj1912 树形dp求直径(新写法),求直径的两端点的更多相关文章
- hdu 2196(方法1:经典树形DP+方法2:树的直径)
Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- 【bzoj2500】幸福的道路 树形dp+倍增RMQ+二分
原文地址:http://www.cnblogs.com/GXZlegend/p/6825389.html 题目描述 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一 ...
- BZOJ 4890: [Tjoi2017]城市 树形dp
标签:树形dp,枚举,树的直径 一上来看到这个题就慌了,只想到了 $O(n^3)$ 的做法. 碰到这种题时要一步一步冷静地去分析,观察数据范围. 首先,$n\leqslant 5000$,所以可以先 ...
- 美团2017年CodeM大赛-初赛B轮 黑白树 (树形dp)
大意: 给定树, 初始每个点全为白色, 点$i$有权值$k_i$, 表示选择$i$后, 所有距离$i$小于$k_i$的祖先(包括i)会变为黑色, 求最少选多少个点能使所有点变为黑色. 链上情况的话, ...
- BZOJ 3572: [Hnoi2014]世界树 虚树 树形dp
https://www.lydsy.com/JudgeOnline/problem.php?id=3572 http://hzwer.com/6804.html 写的时候参考了hzwer的代码,不会写 ...
- HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...
- 浅谈关于树形dp求树的直径问题
在一个有n个节点,n-1条无向边的无向图中,求图中最远两个节点的距离,那么将这个图看做一棵无根树,要求的即是树的直径. 求树的直径主要有两种方法:树形dp和两次bfs/dfs,因为我太菜了不会写后者这 ...
- 树形dp换根,求切断任意边形成的两个子树的直径——hdu6686
换根dp就是先任取一点为根,预处理出一些信息,然后在第二次dfs过程中进行状态的转移处理 本题难点在于任意割断一条边,求出剩下两棵子树的直径: 设割断的边为(u,v),设down[v]为以v为根的子树 ...
- 树形dp - 求树的直径
随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好. 现在已经勘探确定了n个位置可 ...
随机推荐
- vue学习之router
路由文档:https://router.vuejs.org/zh/guide/ 使用vue做spa应用的话,一定会涉及到路由. 安装 安装router插件 npm install vue-router ...
- G - WiFi Password Gym - 101608G (异或思维题+曲尺)
题目链接:https://cn.vjudge.net/contest/285962#problem/G 题目大意:给你n和m,n代表有n个数,然后让你找出一个最长的区间,使得这个区间内的所有的数的‘’ ...
- include指令和<jsp:include>动作标识区别:--不明觉厉 先收藏
<jsp:include> 会通过转发的形式,分别编译被包含的文件,所以不怕重命名:而 include 是将多个被包含的原封不动合并后再一起编译一次,所以不可以重命名. ========= ...
- IOC 和DI的区别
什么是spring的IOC AOP? - Goluck98的专栏 - 博客频道 - CSDN.NET---看前面的那段http://blog.csdn.net/goluck98/article/det ...
- 数据库无法启动ORA-01034: ORACLE not available
错误场景: 1.数据库未启动,查询v$instance报错 SQL> select status from v$instance; select status from v$instance * ...
- C/C++中 # 的神奇作用:把宏参数字符串化/贴合宏参数
一.一般用法 我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起. #define STR(s) #s #define CONS(a,b) int(a##e##b) printf(ST ...
- 论文笔记:Batch Normalization
在神经网络的训练过程中,总会遇到一个很蛋疼的问题:梯度消失/爆炸.关于这个问题的根源,我在上一篇文章的读书笔记里也稍微提了一下.原因之一在于我们的输入数据(网络中任意层的输入)分布在激活函数收敛的区域 ...
- k64 datasheet学习笔记11---Port Control and Interrupts (PORT)
1.前言 Port Control and Interrupt (PORT) 模块提供了port control,digital filtering,和外部中断功能 每个pin的大部分功能可被独立配 ...
- JavaScript拼接html字符串时截断问题
在项目中碰到一个问题,就是JavaScript拼接html标签时,里面特殊字符会有些问题,比如单引号截断配对,导致后面的内容不显示或显示错误.在此记录一下. 下面贴一段简化的代码,若有描述不清的地方还 ...
- a.py
#!/usr/bin/python # -*- coding: UTF-8 -*- import os import sys import re import shutil import glob d ...