• hdu 2196 Computer


    hdu 2196 Computer

    同步:https://buringstraw.win/archives/77/
    树形dp,贼鸡儿难

    题目

    传送门

    给你一棵有边权的树,求每个点到离它最远的点的距离

    输入:

    ​ 一个n

    ​ 接下来n行每行两个整数j,w,其中第i行表示从(i+1)j有一条权值为w的边

    为什么我要把输入放在这里,因为我最开始看错了。。。

    解法

    首先把1(或者其他点)作为根。

    一个节点的最远距离就可以从它的儿子里面或者父亲里面找

    所以只要取他“儿子里的最远距离”和“他父亲的/不经过他的/儿子里的最远距离,加上他父亲到他的边权”中的最大值

    两遍dfs
    第一遍求每个节点儿子理的最远距离,和经过另外一个儿子的最远距离(不是第二远距离)。

    第二遍判断一下能走哪边,然后取max

    if (path[p] == y) {//他爸的最远距离经过了他自己
        f[y][2] = max(f[p][2], f[p][1]) + e[i].w;//能走父亲除了自己外最长的儿子
    }
    else {
        f[y][2] = max(f[p][2], f[p][0]) + e[i].w;//能走父亲最长的儿子
    }
    

    Code

    #include <cstdio>
    #define max(a, b) ((a) > (b) ? (a) : (b))
    
    const int MAXN = 1e4 + 5;
    
    struct ed {
    	int to, nex, w;
    	ed (void) {
    		to = nex = w = 0;
    	}
    } e[MAXN << 1];
    
    int head[MAXN], f[MAXN][3], path[MAXN];
    int newp, n;
    
    void insert (int p1, int p2, int w) {
    	++newp;
    	e[newp].w = w;
    	e[newp].to = p2;
    	e[newp].nex = head[p1];
    	head[p1] = newp;
    }
    
    void dfs1 (int p, int fa) {
    	for (int i = head[p]; i; i = e[i].nex) {
    		int y = e[i].to;
    		if (y != fa) {
    			dfs1(y, p);
    			if (f[p][0] < f[y][0] + e[i].w) {
    				f[p][1] = f[p][0];
    				f[p][0] = f[y][0] + e[i].w;
    				path[p] = y;//p最长的儿子经过了y
    			}
    			else if (f[p][1] < f[y][0] + e[i].w) {
    				f[p][1] = f[y][0] + e[i].w;
    			}
    		}
    	}
    }
    
    void dfs2 (int p, int fa) {
    	for (int i = head[p]; i; i = e[i].nex) {
    		int y = e[i].to;
    		if (y != fa) {
    		if (path[p] == y) {//他爸的最远距离经过了他自己
    		    f[y][2] = max(f[p][2], f[p][1]) + e[i].w;//能走父亲除了自己外最长的儿子
    			}
    			else {
    			    f[y][2] = max(f[p][2], f[p][0]) + e[i].w;//能走父亲最长的儿子
    			}
    		}
    }
    
    int main (void) {
    	while (scanf("%d", &n) != EOF) {
    		newp = 0;
    		for (int i = 1; i <= (n << 1); ++i) {
    			e[i] = ed();
    		}
    		for (int i = 1; i <= n; ++i) {
    			head[i] = 0;
    			path[i] = 0;
    			f[i][0] = f[i][1] = f[i][2] = 0;
    		}
    		for (int i = 2; i <= n; ++i) {
    			int p2, w;
    			scanf("%d%d", &p2, &w);
    			insert(i, p2, w);
    			insert(p2, i, w);
    		}
    		dfs1(1, 0);
    		dfs2(1, 0);
    		for (int i = 1; i <= n; ++i) {
    			printf("%d
    ", max(f[i][0], f[i][2]));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    idea搭建Spring Boot+Mybatis及使用教程
    CentOS 6 安装配置JDK+tomcat环境
    关于无线路由器之间的连接
    关于链表的面试问题(判断一个单链表中是否有环)
    华为机试ACM(字符组合问题)
    Activity的启动模式
    Notification状态栏显示信息
    Java注释Override、Deprecated、SuppressWarnings
    Fragment
    Service
  • 原文地址:https://www.cnblogs.com/buringstraw/p/11795232.html
Copyright © 2020-2023  润新知