【hdu2196】Computer
hdu 2196 computer
题意
给你一棵树,边有权值。
对于每一个点,求其与其距离最远的点的距离。
分析
思路1:树的直径
利用直径的性质进行求解,网上资料很多,这里不赘述。
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=16384;
int n;
struct G
{
int v,d,nxt;
}mp[N<<1];
int tt,hd[N];
int dis[N];
int vis[N];
int mx[N];
inline int read(void)
{
int x=0; char c=getchar();
for (;!isdigit(c);c=getchar());
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x;
}
inline void ins(int u,int v,int d)
{
mp[++tt].v=v;
mp[tt].d=d;
mp[tt].nxt=hd[u];
hd[u]=tt;
}
void dfs(int now)
{
vis[now]=1;
for (int k=hd[now];k;k=mp[k].nxt)
if (!vis[mp[k].v])
{
dis[mp[k].v]=dis[now]+mp[k].d;
dfs(mp[k].v);
}
}
int main(void)
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
while (scanf("%d",&n)!=EOF)
{
int x,y;
memset(hd,0,sizeof hd); tt=0;
for (int i=2;i<=n;i++)
{
x=read(),y=read();
ins(i,x,y),ins(x,i,y);
}
int tmp,tvt;
memset(mx,0,sizeof mx);
memset(dis,0,sizeof dis);
memset(vis,0,sizeof vis);
dfs(1);
for (int i=1;i<=n;i++)
mx[i]=max(mx[i],dis[i]);
tvt=1,tmp=mx[1];
for (int i=2;i<=n;i++)
if (tmp<mx[i]) tvt=i,tmp=mx[i];
memset(dis,0,sizeof dis);
memset(vis,0,sizeof vis);
dfs(tvt);
for (int i=1;i<=n;i++)
mx[i]=max(mx[i],dis[i]);
tvt=1,tmp=mx[1];
for (int i=2;i<=n;i++)
if (tmp<mx[i]) tvt=i,tmp=mx[i];
memset(dis,0,sizeof dis);
memset(vis,0,sizeof vis);
dfs(tvt);
for (int i=1;i<=n;i++)
mx[i]=max(mx[i],dis[i]);
for (int i=1;i<=n;i++)
printf("%d\n",mx[i]);
}
return 0;
}
思路2:二次树形dp
我们要求每个点与其最远点的距离。
我们随便选择一个点构造一棵有根树,那么对于任意一个点,它的直径无非两种情况:
①点向的子树内延伸最长的长度
②点向的子树外延伸最长的长度
对于第一种情况,我们需要记录:从点i往下延伸的最长长度
对于第二种情况,我们需要记录:从点i往外延伸的最长长度
设的父亲为,一种情况是在点时弯了,另一种情况是点往外延伸。
所以
然后需要优化处理。
方法1:从前往后扫一遍,从后往前扫一遍。
方法2:记录最大值和次大值,若i是pre的最大值,那么就取次大,否则取最大。
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
#define per(i,a,b) for (int i=(a);i>=(b);i--)
#define fore(k,u) for (int k=hd[u];k>0;k=mp[k].nx)
#define ed lis[i]
const int N=16384;
const int E=32768;
int n;
struct G
{
int v,d;
int nx;
inline G(int _v=0,int _d=0,int _nx=0)
{
v=_v,d=_d;
nx=_nx;
}
}mp[E];
int tot,hd[N];
int fx[N];
int ux[N]; int lis[E],len;
int ans[N];
inline int rd(void)
{
int x=0,f=1; char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
inline void Ins(int u,int v,int d)
{
mp[++tot]=G(v,d,hd[u]); hd[u]=tot;
mp[++tot]=G(u,d,hd[v]); hd[v]=tot;
}
void FirDFS(int now,int pre)
{
fore(k,now) if (mp[k].v!=pre)
FirDFS(mp[k].v,now);
fore(k,now) if (mp[k].v!=pre)
fx[now]=max(fx[now],fx[mp[k].v]+mp[k].d);
}
void SecDFS(int now,int pre)
{
len=0;
fore(k,now) if (mp[k].v!=pre)
lis[++len]=k;
if (~pre)
{
rep(i,1,len)
ux[mp[ed].v]=max(ux[mp[ed].v],ux[now]);
}
int mx=0;
rep(i,1,len)
{
ux[mp[ed].v]=max(ux[mp[ed].v],mx);
mx=max(mx,fx[mp[ed].v]+mp[ed].d);
}
mx=0;
per(i,len,1)
{
ux[mp[ed].v]=max(ux[mp[ed].v],mx);
mx=max(mx,fx[mp[ed].v]+mp[ed].d);
}
rep(i,1,len)
ux[mp[ed].v]+=mp[ed].d;
fore(k,now) if (mp[k].v!=pre)
SecDFS(mp[k].v,now);
}
int main(void)
{
// freopen("hdu2196.in","r",stdin);
// freopen("hdu2196.out","w",stdout);
while (~scanf("%d",&n))
{
tot=0; memset(hd,0,sizeof hd);
rep(i,2,n)
{
int v=rd(),d=rd();
Ins(i,v,d);
}
memset(fx,0,sizeof fx);
memset(ux,0,sizeof ux);
FirDFS(1,-1);
SecDFS(1,-1);
memset(ans,0,sizeof ans);
rep(i,1,n) ans[i]=max(fx[i],ux[i]);
rep(i,1,n) printf("%d\n",ans[i]);
}
return 0;
}
小结
(1)树的常见方法
①树形dp
②点分治
③树链剖分,dfs序剖分:树–>链
④树上倍增
⑤树上莫队
⑥LCT
当然还要用一些什么树的直径之类的性质。
【hdu2196】Computer的更多相关文章
- 【题解】Computer Network
Description 给你一棵N(N<=10000)个节点的树,求每个点到其他点的最大距离. Input 第一行一个数N.接下来若干行每行两个数k,t描述一条点k到点t的边(输入数据保证无重复 ...
- 【HDOJ2196】Computer(树的直径,树形DP)
题意:给定一棵N个点树,询问这个树里面每个点到树上其他点的最大距离. n<=10000 思路:设f[u,1],f[u,2]为以U为根向下的最长与次长,g[u,1],g[u,2]为从哪个儿子转移来 ...
- Codeforces 716A Crazy Computer 【模拟】 (Codeforces Round #372 (Div. 2))
A. Crazy Computer time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...
- 【HDU 2196】 Computer(树的直径)
[HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...
- 【HDU 2196】 Computer (树形DP)
[HDU 2196] Computer 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 刘汝佳<算法竞赛入门经典>P282页留下了这个问题 ...
- 【HDU 2196】 Computer
[题目链接] 点击打开链接 [算法] 我们知道,一棵树上离某个节点最远的节点,可能是经过它的祖先,再到那个祖先的某个孩子,或者,是它的那颗子树中,离它最远的一个节点,就不难想到以下算法 : 第一遍DF ...
- 企业IT管理员IE11升级指南【3】—— IE11 新的GPO设置
企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...
- 【转】linux和windows下安装python集成开发环境及其python包
本系列分为两篇: 1.[转]windows和linux中搭建python集成开发环境IDE 2.[转]linux和windows下安装python集成开发环境及其python包 3.windows和l ...
- 【转载】如何破解受保护的excel密码
[工具] 1.电脑一台(安装有Microsoft Excel) 2.受保护excel一个 [步骤] 1.首先,打开受保护的Excel表格,按"ALT"+"F11" ...
随机推荐
- 转 Android学习笔记: 学习过程中碰到的一些问题及解决方法
在学习Android开发的过程中遇到了不少的问题,所幸的是最终经过上网查询都得到了解决.现在将我在学习Android开发过程中遇到的一些问题及解决的方法整理如下. 1.R.java不能实时更新 问题描 ...
- 配置 ASP.NET Linux( CentOS 6.5 ) 运行环境 MONO + Jexus
1.更新系统 在命令行下执行 yum –y update 2.安装必要的软件 yum -y install gcc gcc-c++ bison pkgconfig glib2-devel gettex ...
- Java之美[从菜鸟到高手演练]之JDK动态代理的实现及原理
Java之美[从菜鸟到高手演练]之JDK动态代理的实现及原理 JDK动态代理的实现及原理 作者:二青 邮箱:xtfggef@gmail.com 微博:http://weibo.com/xtfg ...
- JQuery增删改查
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 用ActionSupport实现验证
第一种: 只要Action类继承了ActionSupport,就可以用验证方案了 是个原始的方案,需要自己写代码,但是很灵活,登陆案例 不足:业务处理和验证的代码混在一起,不方便验证部分的复用和维护 ...
- JDBC操作Oracle数据库——实际操作过程中的小总结
1.对数据库中,表的每一行数据记录的增删改查 增:insert into 表名 values() 删:delete 表名 where 条件(id=?) 改:update 表名 set 列名=? whe ...
- [Effective Java]第四章 类和接口
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- weblogic与axis2 jar包冲突
1.org.springframework.web.util.NestedServletException: Handler processing failed; nested exception i ...
- Timer 实现2秒4秒连环炸
package com.cn.gbx; import java.util.Date; import java.util.Timer; import java.util.TimerTask; //cla ...
- 个人博客 week1
1:看完教材后不懂的几个问题: (1):团队合作中每个人分工而行,如何保证比较完善的各人之间的信息共享? (2):敏捷开发如何保证开发的效率?即在进行大项目的开发时敏捷开发看上去会很混乱. (3):黑 ...