zoukankan      html  css  js  c++  java
  • Pku2054 Color a Tree


    有一个N个结点的有根树,1是这个树的根。现在要对这N个结点依次进行
    染色,每个结点染色要花费1个单位的时候,同时要满足一个结点仅在其
    父亲被染色后才可被染色,每个结点有个权值Ci,如果我们在第Ti时间对
    i号结点染色,则付出总代价为Sigma(Ti*Ci),1<=i<=N.
    现在给出这个树和每个点的权值,请构造一种染色顺序,使得总代价最小.
    N<=1000

    5 1//5个点
    1 2 1 2 4 //5个点的权值
    1 2
    1 3
    2 4
    3 5
    0 0//整个测试结束
    Sample Output
    33

    Sol:

    第1次找到5这个点,其权值为4,块大小为1,比值是最大的。
    累加值为1*4..1是其父亲点3所在的块的大小。

    第2次找到3这个点,其权值为5,块大小为2,比值是最大的。
    累加值为1*5..1是其父亲点1所在的块的大小。

    第3次找到2这个点,其权值为2,块大小为1,比值是最大的。
    累加值为3*2..3是其父亲点1所在的块的大小。

    第4次找到4这个点,其权值为2,块大小为1,比值是最大的。
    累加值为4*2..4是其父亲点1所在的块的大小。(4的父亲开始是2,但在染2的时候,将4的父亲变成2的父亲,也就是1了。)

    一个非常经典的贪心题.开始每个点i有其权值vi,大小为ti,每次找vi/ti最大的点进行染色,染色的代价为其父亲点所在块的大小。因为要先染其父亲点再染这个点。染完后将所有父亲点指i的,改为指向i的父亲点,并修改i的父亲点所在块的大小.因为数据范围太小了,所以没有用并查集了。这个题还有许多变形,后面再来补。

    #include<bits/stdc++.h>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,r,x,y,fa[1010],v[1010];
    double t[1010];
    int main()
    {
        while(1)
        {
            scanf("%d%d",&n,&r);
            if(n==0&&r==0)
            break;
            int ans=0,sum;
            double mx;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&v[i]);
                ans+=v[i];  //假设每个点都被首先染色过 
                t[i]=1;
            }
            for(int i=1;i<n;i++)
            {
                scanf("%d%d",&x,&y);
                fa[y]=x;
            }
            for(int i=1;i<=n;i++)
            {
                mx=sum=0;
                for(int j=1;j<=n;j++)
                if(v[j]/t[j]>mx&&j!=r)
                        mx=v[j]/t[j],sum=j;
                for(int j=1;j<=n;j++) //将所有点,如果其父亲从前是sum,现在的父亲点改为fa[sum] 
                      if(fa[j]==sum)
                         fa[j]=fa[sum];
                ans+=v[sum]*t[fa[sum]]; 
    			 //取出这个点的权值,及它父亲点的t值,注意是父亲点的.. 
    			 //也就是说当它父亲点染过后,它才被染,所以父亲点所在连通块有多少个点,它被染的序号就是乘上多少 
                v[fa[sum]]+=v[sum];
                t[fa[sum]]+=t[sum];
                v[sum]=0;
            }
            printf("%d\n",ans);
        }
        return 0;
    }
    

      

     https://blog.csdn.net/abc473848880/article/details/13629577

    #include<queue>
    #include<cstdio>
    #include<cstring>
    const int maxn=1010;
    using namespace std;
    struct zy{
    	int num,W,T;
    	zy(){}
    	zy(int _num,int _W,int _T):num(_num),W(_W),T(_T){
    	}
    	bool operator <(const zy &a) const {
    		return W*a.T<a.W*T;
    	}
    };
    inline int getint(){
        char ch=getchar(); int tmp=0;
        while (ch<'0' || ch>'9') ch=getchar();
        for (;ch<='9' && ch>='0';ch=getchar()) tmp=tmp*10+ch-'0';
        return tmp;
    }
    int tot=0;
    int pre[maxn],now[maxn],son[maxn];
    inline void add(int a,int b){
    	pre[++tot]=now[a];
    	now[a]=tot;
    	son[tot]=b;
    }
    bool used[maxn];
    priority_queue<zy>h;
    int n;
    inline void prepare(){
    	tot=0;
    	memset(now,0,sizeof(int)*n);
    	memset(used,0,sizeof(bool)*n);
    	while (!h.empty()) h.pop();
    }
     
    int root;
    int tim[maxn],v[maxn];
    int fa[maxn];
    void init(){
    	n=getint()+1;
    	prepare();
    	n--;
    	root=getint();
    	for (int i=1;i<=n;++i){
    		tim[i]=1;
    		v[i]=getint();
    		h.push(zy(i,v[i],1));
    	}
    	int a,b;
    	for (int i=1;i<n;++i){
    		a=getint();
    		b=getint();
    		add(a,b);
    		fa[b]=a;
    	}
    }
    inline int findmax(int root){
    	while (used[h.top().num] || h.top().num==root) h.pop();
    	return h.top().num;
    }
     
    inline int find(int x){
    	if (used[fa[x]]) fa[x]=find(fa[x]);
    	return fa[x];
    }
     
    inline void Union(int a,int b){
    	v[b]+=v[a];
    	tim[b]+=tim[a];
    	for (int p=now[a];p;p=pre[p])
    		fa[son[p]]=b;
    }
     
    void work(){
    	int ans=0;
    	for (int i=1;i<n;++i){
    		int tmp=findmax(root);
    		used[tmp]=1;
    		int pre=find(tmp);
    		ans+=tim[pre]*v[tmp];
    		Union(tmp,pre);
    		h.push(zy(pre,v[pre],tim[pre]));
    	}
    	ans+=v[root];
    	printf("%d\n",ans);
    }
     
    int main()
    {
    	while (1){
    		init();
    		if (!root) break;
    		work();
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    接口调用实现类&& 为什么Autowired定义在接口上
    getSuperclass与getGenericSuperclass区别
    Error resolving template “pages”, template might not exist or might not be accessible by any of the configured Template Resolver 或者 springboot使用thymeleaf时报html没有结束标签
    dcm4che-core导包失败! mvn pom文件导包总是失败
    使用IDEA springboot 如何通过mybatis-generator自动生成mapper dao model
    《剑指offer》第三十八题:字符串的排列
    《剑指offer》第三十七题:序列化二叉树
    《剑指offer》第三十六题:二叉搜索树与双向链表
    《剑指offer》第三十五题:复杂链表的复制
    《剑指offer》第三十四题:二叉树中和为某一值的路径
  • 原文地址:https://www.cnblogs.com/cutemush/p/11679294.html
Copyright © 2011-2022 走看看