HDU ACM 1055 Color a Tree->树上的贪心

题意:给一棵树染色,这棵树有n个节点,根结点是r。每个结点都有一个权值ci,开始时间为0,每染色一个结点需要耗时1,每个结点染色代价为ci*ti(ti为当前时间),每个结点只有在父结点被染色的条件下才能被染色。求染完整棵树要花费的最小代价。

分析:贪心总体思路,每次找一个权值最大的节点,如果是根节点,则首先对它染色,否则的话可以得出一个结论,在它父亲已经染色的情况下,立刻给它染色是最优的。对于第二种情况,当它不是根节点,且已对它父亲染了色,则一定会立刻对它染色,所以可以把它和它父亲合并为同一个节点,它和它父亲的儿子都成为了新节点的儿子,它的父亲的父亲则是新节点的父亲。为了能继续贪心,给每个节点赋上两个权值,ti表示对第i个节点图色所需时间(第i个节点实际包含的节点数),si表示第i个节点的总权值(第i个节点实际包含的节点的权值和)。此时,定义一个节点的权值等于si比上ti。可以证明在新的权值定义下,以上贪心同样成立。

结论:对于一个非根结点,它具有非根结点的最大权值,那么访问完它的父节点后立即访问它能使得代价最小。

使用并查集。

过程;

1、初始将序列中的time[i]都置为1,w[i]置为c[i];

2、查找最大的w[i],得到位置;

3、将该位置的s与它的父节点s合并(就是C_i / T_i,C_i = c[该节点] + c[父节点],T_i = time[该节点]+time[父节点])得新的父节点w[](w[父节点] = C_i / T_i),如果有节点与pos相连,让它指向pos的父节点。

4、重复2、3,直到合并完(或者所有点都被访问);

最终会得到一个访问序列,该序列能得到最小的染色权值。

#include<iostream>
using namespace std;

#define N 1010
double b[N];      //合并节点权值和
int Next[N];      //记录最优访问的下一个节点
int f[N];         //记录父节点
int cnt[N];       //合并节点的节点数
int fa[N];        //并查集使用
bool vis[N];
int a[N];      //权值

int child(int r)  //找到最优访问序列的最后一个节点(子节点)
{
	if(Next[r]==r) return r;
	return child(Next[r]);
}

int father(int x)  //找到祖先节点,带路径压缩
{
	if(fa[x]==x) return x;
	fa[x]=father(fa[x]);
	return fa[x];
}

int sovle(int n,int r)
{
	double max;
	int j,i,u,v,ans,k;

	memset(vis,false,sizeof(vis));
	vis[r]=true;
	for(j=1;j<n;j++)  //处理n-1次
	{
		max=0;
		for(i=1;i<=n;i++)
			if(!vis[i] && max<b[i]/cnt[i])
			{
				max=b[i]/cnt[i];
				v=i;
			}
		u=child(f[v]);
		Next[u]=v;
		fa[v]=u;
		u=father(v);  //这句并不多余,可以进行路径压缩
		cnt[u]+=cnt[v];
		b[u]+=b[v];
		vis[v]=true;
	}
	ans=0;
	k=1;
	while(r!=Next[r])  //处理最优序列
	{
		ans+=k*a[r];
		k++;
		r=Next[r];
	}
	ans+=k*a[r];
	return ans;
}

int main()
{
	int n,i,u,v,r;

	while(scanf("%d%d",&n,&r)==2 && n+r)
	{
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			b[i]=a[i]*1.0;
			fa[i]=f[i]=Next[i]=i;
			cnt[i]=1;
		}
		for(i=1;i<n;i++)
		{
			scanf("%d%d",&u,&v);
			f[v]=u;
		}
		printf("%d\n",sovle(n,r));
	}
    return 0;
}
时间: 2024-12-15 03:27:55

HDU ACM 1055 Color a Tree->树上的贪心的相关文章

HDU 4912 Paths on the tree LCA 排序贪心

lca... 排个序然后暴力保平安 _(:зゝ∠)_ #pragma comment(linker, "/STACK:102400000,102400000") #include"cstdio" #include"iostream" #include"set" #include"queue" #include"string.h" using namespace std; #define

HDU 1055 Color a Tree

题目:Color a Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=1055 题意:给一棵树,要给树上每一个结点染色,第i 个结点染色需要代价为:t * w[i] (t 表示i 结点是第几个染色的),还有一个前提是:要给i 结点染色,必须先给i 结点的父结点染色(根结点随便染). 思路: 贪心. 假定当前未染色的结点中权值最大的是A结点,如果A结点上方都染完色,那么现在一定是对A结点进行染色. 理解如下: 假设在上述情况下先对其他结点染色,在

poj 2054 Color a Tree 据说是贪心

Color a Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 7112   Accepted: 2438 Description Bob is very interested in the data structure of a tree. A tree is a directed graph in which a special node is singled out, called the "root&qu

HDU - 6241 :Color a Tree(不错的二分)

Bob intends to color the nodes of a tree with a pen. The tree consists of NN nodes. These nodes are numbered 1,2,...,N1,2,...,N. The root of the tree is node 11. The initial color of each node is white. Bob can use one unit energy to color one node i

HDU ACM 2489 Minimal Ratio Tree

Minimal Ratio TreeTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3057    Accepted Submission(s): 917 Problem Description For a tree, which nodes and edges are all weighted, the ratio of it is

HDU 4912 Paths on the tree(LCA+贪心)

题目链接 Paths on the tree 来源  2014 多校联合训练第5场 Problem B 题意就是给出m条树上的路径,让你求出可以同时选择的互不相交的路径最大数目. 我们先求出每一条路径(u, v)中u和v的LCA:w,按照路径的w的深度大小deep[w]对所有的路径排序. deep[w]越大,排在越前面. 然后从第一条路径开始一次处理,看c[u]和c[v]是否都没被标记过,如果都没被标记过则我们把这条路径选上,把答案加1. 同时标记以w为根的子树的节点为1,方便后续对c数组的查询

HDU ACM 1052 Tian Ji -- The Horse Racing 贪心

#include<iostream> #include<algorithm> using namespace std; int main() //贪心 { int n,money,i,j,i1,j1; int a[1005],b[1005]; while(cin>>n && n) { for(i=0;i<n;i++) cin>>a[i]; for(i=0;i<n;i++) cin>>b[i]; sort(a,a+n);

hdu 1055 &amp; poj 2054 Color a Tree 树&amp;贪心 找最大费用点和父节点合并

Color a Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 7144 Accepted: 2458 Description Bob is very interested in the data structure of a tree. A tree is a directed graph in which a special node is singled out, called the "root"

hdu 4603 Color the Tree 2013多校1-4

这道题细节真的很多 首先可以想到a和b的最优策略一定是沿着a和b在树上的链走,走到某个点停止,然后再依次占领和这个点邻接的边 所以,解决这道题的步骤如下: 预处理阶段: step 1:取任意一个点为根节点,找出父子关系并且对这个树进行dp,求出从某个节点出发往下所包含的所有边的权值总和  复杂度O(n) step 2:从tree dp 的结果中计算对于某个节点,从某条边出发所包含的边的综合,并且对其从大到小进行排序 复杂度O(n*logn) step 3:dfs求出这颗树的欧拉回路,以及每个点的