zoukankan      html  css  js  c++  java
  • Dus on tree 月出皎兮,佼人僚兮。

    https://ac.nowcoder.com/acm/contest/6037/F

    很诡异,对于8 3 2 1 1这种,答案是7(3+2+1+1), 对于6 5 4 3 2 1这种,是(6+5+4+3+2+1)/2

    所以求出每种颜色的最大数量  还有颜色总数就能在O(1)算出来一棵树了。但是吧。。。真想不到

    具体看代码吧,有dus on tree板子

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<set>
    #include<vector>
    using namespace std;
    const int maxn = 2e5 + 100;
    typedef long long ll;
    vector<int>G[maxn];
    
    
    void add(int be, int en) {
    	G[be].push_back(en);
    }
    int siz[maxn];
    int son[maxn];
    ll sum[maxn];
    ll ans[maxn];
    ll b[maxn];
    ll cnt[maxn];
    
    ll list[maxn];
    
    ll maxx = 0;
    
    int dfs(int x, int fa) {
    	siz[x] = 1;
    	sum[x] = b[x];
    	int c = 0;
    	for (int p : G[x]) {
    		if (p == fa) continue;
    		dfs(p, x);
    		siz[x] += siz[p];
    		sum[x] += sum[p];
    
    		if (siz[p] > c) {
    			c = siz[p];
    			son[x] = p;
    		}
    	}
    	return 0;
    }
    
    int cal(int x, int fa, int f) {
    	cnt[list[x]] += b[x];
    	maxx = max(maxx, cnt[list[x]]);
    	for (int p : G[x]) {
    		if (p == fa || p == f) continue;
    		cal(p, x, f);
    	}
    	return 0;
    }
    int cal2(int x, int fa, int f) {
    	cnt[list[x]] -= b[x];
    	for (int p : G[x]) {
    		if (p == fa ) continue;
    		cal2(p, x, f);
    	}
    	return 0;
    }
    
    int dfs2(int x, int fa, int flag) {
    	for (int p : G[x]) {
    		if (p == fa) continue;
    		if (p == son[x]) continue;
    		dfs2(p, x, 0);//把轻儿子算一遍
    	}
    	if (son[x] != 0) {
    		dfs2(son[x], x, 1);//最后算重儿子
    	}
    
    	cal(x, fa, son[x]);//重儿子算过了,不必重算
    
    	if (maxx <= sum[x] / 2) {
    		ans[x] = sum[x] / 2;
    	}
    	else {
    		ans[x] = sum[x] - maxx;
    	}
    
    	if (flag == 0) {//清空
    		maxx = 0;
    		cal2(x, fa, son[x]);
    	}
    	return 0;
    }
    
    
    
    int main() {
    	int n;
    	int be;
    	scanf("%d", &n);
    	int x, y;
    	for (int i = 2; i <= n; i++) {
    		scanf("%d %d", &x, &y);
    		add(x, y);
    		add(y, x);
    	}
    	for (int i = 1; i <= n; i++) {
    		scanf("%lld %lld", &list[i], &b[i]);
    	}
    	dfs(1, -1);
    	dfs2(1, -1, 0);
    
    
    	for (int i = 1; i <= n; i++) {
    		printf("%lld
    ", ans[i]);
    	}
    	return 0;
    }
    

      

    寻找真正的热爱
  • 相关阅读:
    原:Myeclipse10+Egit+bitbucket实现版本控制
    Myeclipse10使用git
    MyEclipse 10 下在线安装插件
    转:git windows中文目录乱码问题解决
    STUN和TURN技术浅析
    原:android4.2.2蓝牙源码阅读--bluedroid部分
    原创:超简单!windows配置NDK开发环境使用JNI
    c++对象的生命周期
    C++中虚析构函数的作用
    windows 命令行下 简单好用的查看端口占用情况的方法
  • 原文地址:https://www.cnblogs.com/lesning/p/13536346.html
Copyright © 2011-2022 走看看