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的更多相关文章

  1. 【题解】Computer Network

    Description 给你一棵N(N<=10000)个节点的树,求每个点到其他点的最大距离. Input 第一行一个数N.接下来若干行每行两个数k,t描述一条点k到点t的边(输入数据保证无重复 ...

  2. 【HDOJ2196】Computer(树的直径,树形DP)

    题意:给定一棵N个点树,询问这个树里面每个点到树上其他点的最大距离. n<=10000 思路:设f[u,1],f[u,2]为以U为根向下的最长与次长,g[u,1],g[u,2]为从哪个儿子转移来 ...

  3. 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 ...

  4. 【HDU 2196】 Computer(树的直径)

    [HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...

  5. 【HDU 2196】 Computer (树形DP)

    [HDU 2196] Computer 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 刘汝佳<算法竞赛入门经典>P282页留下了这个问题 ...

  6. 【HDU 2196】 Computer

    [题目链接] 点击打开链接 [算法] 我们知道,一棵树上离某个节点最远的节点,可能是经过它的祖先,再到那个祖先的某个孩子,或者,是它的那颗子树中,离它最远的一个节点,就不难想到以下算法 : 第一遍DF ...

  7. 企业IT管理员IE11升级指南【3】—— IE11 新的GPO设置

    企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...

  8. 【转】linux和windows下安装python集成开发环境及其python包

    本系列分为两篇: 1.[转]windows和linux中搭建python集成开发环境IDE 2.[转]linux和windows下安装python集成开发环境及其python包 3.windows和l ...

  9. 【转载】如何破解受保护的excel密码

    [工具] 1.电脑一台(安装有Microsoft Excel) 2.受保护excel一个 [步骤] 1.首先,打开受保护的Excel表格,按"ALT"+"F11" ...

随机推荐

  1. 源码安装python

    编译安装新版本python 一般来说python是linux系统的标配,但是版本一般却很老,而系统上面的很多服务可能与老的python存在依赖关系,我们又不能直接卸载.所以一般,我们可以在一个单独的目 ...

  2. 预编译那些事#define后面只跟一个“参数”

    一般情况下,源程序中所有的行都参加编译.但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”.有时,希望当满足某条件时对一组语句进行编译,而当条 ...

  3. Linux系统下修改环境变量PATH路径的三种方法

    这里介绍Linux的知识,比如把/etc/apache/bin目录添加到PATH中有三种方法,看完之后你将学会Linux系统下如何修改环境变量PATH路径,需要的朋友可以参考下 电脑中必不可少的就是操 ...

  4. 动手动脑final

    1.回答问题 1. 下边的程序运行结果是什么? 2.   你如何解释会得到这样的输出? 3.   计算机是不会出错的,之所以得到这样的运行结果也是有原因的,那么从这些运行结果中,你能总结出Java的哪 ...

  5. TCP连接的状态详解以及故障排查

    我们通过了解 TCP各个状态 ,可以排除和定位网络或系统故障时大有帮助. 一.TCP状态 LISTENING :侦听来自远方的TCP端口的连接请求 . 首先服务端需要打开一个 socket 进行监听, ...

  6. Linux内核中的GPIO系统之(3):pin controller driver代码分析

    一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...

  7. eclipse 恢复SVN无法还原的文件 svn使用了还原,但本地的没有提交找回没提交代码的方法

    http://blog.sina.com.cn/s/blog_750167060102vd2n.html

  8. python_way day17 html-day3 前端插件(fontawsome,easyui,bootstrap,jqueryui,bxslider,jquerylazyload),web框架

    python_way day17 一.模板插件 图标的插件 fontawsome: 后台管理: easyui jqueryui 很多网站都会用: bootstrap :引入jQuery:(2.x,1. ...

  9. new的深一步

    new的深一步 new运算符 用于创建对象和条用构造函数 new修饰符 用于隐藏基类中被继承的成员 new约束 用于在泛型声明中约束可能用作类型参数的参数类型 new运算符 用于创建对象和调用构造函数 ...

  10. Win7_关闭休眠文件hiberfil.sys

    1. C盘根目录下 hiberfil.sys 占用好几G空间,直接删 删不掉,也不推荐直接删. 2. 2.1.命令窗口中输入 powercfg -h off,即可关闭休眠功能,同时 Hiberfil. ...