zoukankan      html  css  js  c++  java
  • 【UOJ #105】【APIO2014】Beads and wires

    http://uoj.ac/problem/105
    好神的dp啊。
    确定一个点为根之后,蓝线只能是竖着的,不能横跨兄弟。
    枚举每个点为根进行树形dp是(O(n^2))的,(f(x,0/1))表示以(x)为根的子树中(x)是否作为蓝线终点的最大值。
    更科学的做法:(O(1))把根从一个father转移到它的son。
    需要维护(f(father,1))的最大和次大(防止son作为最大转移到father),利用father的信息更新(f(son,0))(f(son,1))的最大和次大(这里的换根不是真正把根换到son,只是说换根后son作为根的信息是正确的,不需要修改father的信息)。
    时间复杂度(O(n))

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N = 200003;
    
    struct node {int nxt, to, w;} E[N << 1];
    int cnt = 0, point[N], f[N][2], fs[N][2];
    
    void ins(int u, int v, int w) {E[++cnt] = (node) {point[u], v, w}; point[u] = cnt;}
    
    int n, son[N], tot, fadis[N];
    
    void dfs(int x, int fa) {
    	for (int i = point[x]; i; i = E[i].nxt)
    		if (E[i].to != fa) fadis[E[i].to] = E[i].w, dfs(E[i].to, x);
    	
    	tot = 0;
    	for (int i = point[x]; i; i = E[i].nxt)
    		if (E[i].to != fa) son[++tot] = E[i].to;
    	
    	for (int i = 1; i <= tot; ++i)
    		f[x][0] += max(f[son[i]][0], f[son[i]][1]);
    	
    	int mx = -0x7fffffff, mxs = -0x7fffffff, num;
    	for (int i = 1; i <= tot; ++i) {
    		num = f[son[i]][0] + fadis[son[i]] - max(f[son[i]][0], f[son[i]][1]);
    		if (num >= mx) mxs = mx, mx = num;
    		else if (num > mxs) mxs = num;
    	}
    	
    	f[x][1] = mx + fadis[x] + f[x][0];
    	fs[x][1] = mxs + fadis[x] + f[x][0];
    }
    
    void move(int x, int y, int d) {
    	int t, fx0 = f[x][0], fx1 = f[x][1], fxs1 = fs[x][1];
    	if (fx1 == fx0 - max(f[y][1], f[y][0]) + f[y][0] + fadis[y]) fx1 = fxs1;
    	fx0 -= max(f[y][1], f[y][0]);
    	fx1 -= max(f[y][1], f[y][0]);
    	fx1 += d;
    	f[y][0] += max(fx0, fx1);
    	f[y][1] += max(fx0, fx1);
    	fs[y][1] += max(fx0, fx1);
    	f[y][1] -= d; fs[y][1] -= d;
    	if ((t = f[y][0] - max(fx0, fx1) + fx0 + d) >= f[y][1])
    		fs[y][1] = f[y][1], f[y][1] = t;
    	else if (t > fs[y][1]) fs[y][1] = t;
    }
    
    int ans = 0;
    
    void dfsmove(int x, int fa) {
    	ans = max(ans, f[x][0]);
    	for (int i = point[x]; i; i = E[i].nxt) {
    		int v = E[i].to;
    		if (v == fa) continue;
    		move(x, v, E[i].w);
    		dfsmove(v, x);
    	}
    }
    
    int main() {
    	scanf("%d", &n);
    	int u, v, e;
    	for (int i = 1; i < n; ++i) {
    		scanf("%d%d%d", &u, &v, &e);
    		ins(u, v, e);
    		ins(v, u, e);
    	}
    	
    	dfs(1, 0);
    	dfsmove(1, 0);
    	printf("%d
    ", ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    Haproxy 配置项及配置实例-Haproxy入门教程
    Spring Boot 配置-Spring Boot教程深入浅出系列
    RMI 接口和类概述-RMI快速入门教程
    分布式和非分布式模型对比-RMI快速入门教程
    RMI分布式对象模型-RMI快速入门教程
    RMI介绍-RMI快速入门教程
    Qt编写可视化大屏电子看板系统17-柱状堆积图
    Qt开发经验小技巧161-165
    Qt编写安防视频监控系统60-子模块4云台控制
    MyBatis的关联映射,resultMap元素之collection子元素,实现一对多关联关系(节选自:Java EE企业级应用开发教程)
  • 原文地址:https://www.cnblogs.com/abclzr/p/6728152.html
Copyright © 2011-2022 走看看