zoukankan      html  css  js  c++  java
  • HDU-2196 Computer (树形DP)

    题目大意:在一棵带边权的有根树中,对于每个点,找出它与离它最远的那个点的之间的距离。

    题目分析:对于一个点,离它最远的点只有两种情况,一是它到叶子节点的最远距离,一是与它父亲的距离加上他的父亲到叶子节点的最远距离。因为它的父亲到叶子的最远距离的那条路径可能恰好经过它自己,所以还要求出每个点到叶子节点的次大距离。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<vector>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    const int N=10010;
    
    struct Edge
    {
    	int to,w,nxt;
    };
    Edge e[N*2];
    int n,cnt;
    int head[N];
    int maxn[N];
    int smaxn[N];
    int maxid[N];
    int smaxid[N];
    
    void init()
    {
    	cnt=0;
    	memset(head,-1,sizeof(head));
    }
    
    void add(int u,int v,int w)
    {
    	e[cnt].to=v;
    	e[cnt].w=w;
    	e[cnt].nxt=head[u];
    	head[u]=cnt++;
    }
    
    void read()
    {
    	int a,b;
    	for(int i=2;i<=n;++i){
    		scanf("%d%d",&a,&b);
    		add(i,a,b);
    		add(a,i,b);
    	}
    }
    
    void dfs1(int u,int fa)
    {
    	maxn[u]=smaxn[u]=0;
    	for(int i=head[u];i!=-1;i=e[i].nxt){
    		int v=e[i].to;
    		if(v==fa) continue;
    		dfs1(v,u);
    		if(e[i].w+maxn[v]>smaxn[u]){
    			smaxn[u]=e[i].w+maxn[v];
    			smaxid[u]=v;
    			if(smaxn[u]>maxn[u]){
    				swap(smaxn[u],maxn[u]);
    				swap(smaxid[u],maxid[u]);
    			}
    		}
    	}
    }
    
    void dfs2(int u,int fa)
    {
    	for(int i=head[u];i!=-1;i=e[i].nxt){
    		int v=e[i].to;
    		if(v==fa)continue;
    		if(v==maxid[u]){
    			if(e[i].w+smaxn[u]>smaxn[v]){
    				smaxn[v]=e[i].w+smaxn[u];
    				smaxid[v]=u;
    				if(smaxn[v]>maxn[v]){
    					swap(smaxn[v],maxn[v]);
    					swap(smaxid[v],maxid[v]);
    				}
    			}
    		}else{
    			if(e[i].w+maxn[u]>smaxn[v]){
    				smaxn[v]=e[i].w+maxn[u];
    				smaxid[v]=u;
    				if(smaxn[v]>maxn[v]){
    					swap(smaxn[v],maxn[v]);
    					swap(smaxid[v],maxid[v]);
    				}
    			}
    		}
    		dfs2(v,u);
    	}
    }
    
    void solve()
    {
    	dfs1(1,-1);
    	dfs2(1,-1);
    	for(int i=1;i<=n;++i)
    		printf("%d
    ",maxn[i]);
    }
    
    int main()
    {
    	while(~scanf("%d",&n))
    	{
    		init();
    		read();
    		solve();
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    How can i install ctags in centos 6.4
    [转载] Ubuntu Vim powerline 插件
    Vim 相关网页
    [转载] vim技巧:设置空格和Tab字符可见
    Don't trust cplusplus.com, it's crap. If any, go to cppreference.com.
    Vim yank only 50 lines
    按进程名终止进程
    Shell 脚本 Tips
    Bash 脚本 逐行处理文本文件的内容
    生成并配置https本地证书
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5342435.html
Copyright © 2011-2022 走看看