Color a Tree

POJ

Meaning of the questions: one has \ (n (1≤n≤1000) \) nodes of the tree, each node \ (i (1≤i≤n) \) has a weight \ (a_i \) now. put all of this tree node staining, coloring rule is: root \ (root \) . can always be stained; for other nodes before being dyed its parent node must have been infected with each color staining consideration is \ (a * T [I] \) , where \ (T \) representing the current many times staining seeking a minimum total cost of this tree staining.

Analysis: greedy strategy: the maximum weight of the dyeing point and its parent node is continuous, that is the point of maximum weight will be stained immediately after its father staining. So we can consider merging these two points, the right to a new point of merger obtained was the average of these two points, so we continue to take the point of maximum weights in the trees, and then merge with its parent node, while the computational cost It can be.

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=1005;
int a[N],fa[N],size[N],visit[N];
int tot,head[N],nxt[N*2],to[N*2];
inline void add(int a,int b){nxt[++tot]=head[a];head[a]=tot;to[tot]=b;}
inline int find(int n,int root){
    int node;double maxn=0.0;
    for(int i=1;i<=n;++i)
        if(!visit[i]&&i!=root&&maxn<(double)a[i]/size[i]){
            maxn=(double)a[i]/size[i];node=i;
        }
    return node;
}
inline void Union(int pre,int node){
    a[pre]+=a[node];size[pre]+=size[node];
    for(int i=head[node];i;i=nxt[i])fa[to[i]]=pre;
}
inline int solve(int n,int root){
    int ans=0;
    for(int i=1;i<n;++i){//记得只要n-1次
        int node=find(n,root);//找到平均权值最大的点
        visit[node]=1;
        int pre=fa[node];
        while(visit[pre])pre=fa[pre];//找到该点的父亲节点
        ans+=a[node]*size[pre];//计算代价
        Union(pre,node);//合并
    }
    return ans+a[root];
}
int main(){
    while(1){
        int n=read(),root=read();if(!n&&!root)break;
        tot=0;memset(head,0,sizeof(head));memset(visit,0,sizeof(visit));
        for(int i=1;i<=n;++i)a[i]=read(),size[i]=1;
        for(int i=1;i<n;++i){
            int x=read(),y=read();
            add(x,y);fa[y]=x;
        }
        printf("%d\n",solve(n,root));
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/PPXppx/p/11236033.html