• UVA1205 color a tree


    好神的一道题

    每一步在可以被染色的点选权值最大的点是错误想法,很容易(hack)

    正确性质:树中除根节点以外最大权值的点,一定会在它父亲节点后立即染色

    合并这两个节点,得到节点为两个权值的平均值

    假设三个点

    权值(x,y,z)(x,y)连续进行操作,就有两种染色方案

    先染(x,y) ,代价(x+2y+3z) 先染(z),代价(z+2z+3y)

    考虑两个代价的大小关系,把两个式子都加上((z-y))再除以二

    得到(1.(x+y)/2+2z) (2.z+2((x+y)/2))

    所以合并两个点是正确的,

    等效权值:原始点权值总和/该点包含的原始点数

    struct node{int f,siz,val;}a[N];
    int n,R,fa[N]; bool vis[N];
    priority_queue<pair<double,int> >q;
    int find(int x){return fa[x] == x ? x : fa[x] = find(fa[x]);}
    int main(){
    	while(~scanf("%d%d",&n,&R)){
    		int ans = 0,u,v;
    		for(int i = 1;i <= n;++i){
    			scanf("%d",&a[i].val);
    			a[i].siz = 1; ans += a[i].val;
    			fa[i] = i;vis[i] = 0;
    			if(i == R) continue;
    			q.push(make_pair(a[i].val,i));
    		}
    		for(int i = 1;i < n;++i){
    			scanf("%d%d",&u,&v);
    			a[v].f = u;
    		}
    		while(!q.empty()){
    			int p = q.top().second;
    			q.pop();
    			if(vis[p]) continue;
    			vis[p] = 1;
    			int f = find(a[p].f);
    			ans += a[f].siz * a[p].val;
    			a[f].val += a[p].val;
    			a[f].siz += a[p].siz;
    			if(f != R) q.push(make_pair((double)a[f].val/a[f].siz,f));
    			fa[p]=f;
    		}
    		printf("%d
    ",ans);	
    	}
    }
    
  • 相关阅读:
    vi使用方法详细介绍
    Jenkins实现Android自动化打包
    JSON知识总结
    React Native中pointerEvent属性
    从零学React Native之06flexbox布局
    Android Http实现文件的上传和下载
    从零学React Native之05混合开发
    React Native声明属性和属性确认
    从零学React Native之04自定义对话框
    Android 在图片的指定位置添加标记
  • 原文地址:https://www.cnblogs.com/shikeyu/p/13738244.html
Copyright © 2020-2023  润新知