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

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" of the tree, and there is a unique path from the root to each of the other nodes.

Bob intends to color all the nodes of a tree with a pen. A tree has N nodes, these nodes are numbered 1, 2, ..., N. Suppose coloring a node takes 1 unit of time, and after finishing coloring one node, he is allowed to color another. Additionally, he is allowed
to color a node only when its father node has been colored. Obviously, Bob is only allowed to color the root in the first try.

Each node has a "coloring cost factor", Ci. The coloring cost of each node depends both on Ci and the time at which Bob finishes the coloring of this node. At the beginning, the time is set to 0. If the finishing time of coloring node i is Fi, then the coloring
cost of node i is Ci * Fi.

For example, a tree with five nodes is shown in Figure-1. The coloring cost factors of each node are 1, 2, 1, 2 and 4. Bob can color the tree in the order 1, 3, 5, 2, 4, with the minimum total coloring cost of 33.

Given a tree and the coloring cost factor of each node, please help Bob to find the minimum possible total coloring cost for coloring all the nodes.

Input

The input consists of several test cases. The first line of each case contains two integers N and R (1 <= N <= 1000, 1 <= R <= N), where N is the number of nodes in the tree and R is the node number of the root node. The second line contains N integers, the
i-th of which is Ci (1 <= Ci <= 500), the coloring cost factor of node i. Each of the next N-1 lines contains two space-separated node numbers V1 and V2, which are the endpoints of an edge in the tree, denoting that V1 is the father node of V2. No edge will
be listed twice, and all edges will be listed.

A test case of N = 0 and R = 0 indicates the end of input, and should not be processed.

Output

For each test case, output a line containing the minimum total coloring cost required for Bob to color all the nodes.

Sample Input

5 1

1 2 1 2 4

1 2

1 3

2 4

3 5

0 0

Sample Output

33

题意:

有一颗树,需要给他每个点都染色。节点标号从1-n,每个节点的权值在输入的第二行给出。 要求必须父节点已经染色,子节点才可以染色,需要按拓扑顺序染色。然后每个节点需要一个单位的染色时间。时间从1开始,计算费用时,每个节点的费用是当前时间*节点的权值。

第三行开始 接下来的输入是树的父亲和儿子的关系。

做法:

贪心,开始把每个点各自看成一个团。然后那个团的权值和  以及 这个团有多少个点 都记录在这个团的最顶上的祖先点上。 然后每次贪心 找 出( 权值和/点数 ) 最大的那个团。然后用链表的记录方式  跟新 这个团的祖先 与 其父亲的关系。并把这个团 与那个父亲所在的团合并。

最后从root开始,历遍这个链表,时间从1开始,计算出总的花费。

为什么这么贪心,因为如果点多的团先连,就代表先走点多的团,花费的时间会更多,后面的花费会增加。  所以优先选择团是和点的数量成反比和团的总权值成正比的把。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <stack>
#include <queue>
#include <vector>
#include <deque>
#include <set>
#include <map> 

int w[1010];//团的权值
int root,num[1010];//团的点数
int n,c[1010];   //点的权值
int nex[1010],pre[1010]; //链表的记录
int fa[1010],vis[1010]; //父节点 和 有无访问过

int find()
{
	double maxx=-1;
	int id=-1;
	for(int i=1;i<=n;i++)
	{
		if(i!=root&&(1.0*w[i]/num[i])>maxx&&!vis[i])
		{
			maxx=(1.0*w[i]/num[i]);
			id=i;
		}
	}

	vis[id]=1;
	return id;
}

void unit(int p)
{
	int i;
	for(i=fa[p];~pre[i];i=pre[i]){} //找出父节点团的 祖先  也就是这个团中最先染色的点

	w[i]+=w[p];
	num[i]+=num[p];

	for(i=fa[p];~nex[i];i=nex[i]){}	//找出父节点团中 最后一个染色的点

	pre[p]=i;
	nex[i]=p;
}

int main ()
{
	while(scanf("%d%d",&n,&root),n||root)
	{
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&w[i]);
			c[i]=w[i];
			num[i]=1;
			pre[i]=nex[i]=-1;
			vis[i]=0;
		}
		int u,v;
		for(int i=1;i<n;i++)
		{
			scanf("%d%d",&u,&v);
			fa[v]=u;
		}
		while(1)
		{
			int tem=find();
			if(tem==-1)
				break;
			unit(tem);
		}

		int time=1;
		int ans=0;
		for(int i=root;~i;i=nex[i])
		{
			ans+=time*c[i];
			time++;
		}
		printf("%d\n",ans);

	}
    return 0;
}
/*
5 1
1 2 1 2 4
1 2
1 3
2 4
3 5
0 0
*/ 
时间: 2024-08-07 04:31:16

hdu 1055 & poj 2054 Color a Tree 树&贪心 找最大费用点和父节点合并的相关文章

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

poj 2054 Color a Tree

很有意思的一道贪心题,自己没想出来,理解了一下别人的思路 参考:http://www.cnblogs.com/yu-chao/archive/2012/02/19/2358565.html http://my.oschina.net/locusxt/blog/210536 题目大意:给你一颗树,树上每个节点都有自己的权值,现在要把这棵树上的所有节点染上颜色,每染一个节点需要一个单位的时间,染一个点的花费是该点的权值乘以当前时间(时间从1开始).规定在染当前点之前,必须先染他的父亲节点,求最小的花

poj 2054 Color a Tree(贪心)

# include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int father[1010]; int next[1010];//当前集合的下个元素(包括i) int pre[1010];//当前集合的上个元素(包括i) int num[1010];//num[i]当前集合储存的点的个数(包括i) int vis[1010]; int sum[1010];//当前

POJ 2054 Color a Tree#贪心(难,好题)

题目链接 代码借鉴此博:http://www.cnblogs.com/vongang/archive/2011/08/19/2146070.html 其中关于max{c[fa]/t[fa]}贪心原则,此博有很好的解释:http://www.cnblogs.com/rainydays/p/3271277.html 在此引用其中几段话: 试想,如果没有父节点排在节点之前的限制,那么这个题目非常简单,只需要将结点按照权值从大到小排列即可.加上了这个限制之后,如果权值最大的那个节点一旦满足了条件(父节点

poj 2054 Color a Tree(贪婪)

# include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int father[1010]; int next[1010];//当前集合的下个元素(包含i) int pre[1010];//当前集合的上个元素(包含i) int num[1010];//num[i]当前集合储存的点的个数(包含i) int vis[1010]; int sum[1010];//当前

poj 3016 K-Monotonic 左偏树 + 贪心 + dp

//poj 3016 K-Monotonic//分析:与2005年集训队论文黄源河提到的题目类似,给定序列a,求一序列b,b不减,且sigma(abs(ai-bi))最小.//思路:去除左偏树(大根堆)一半的节点(向上取整),让左偏树的根节点上存放中位数:每个左偏树的根节点表示一个等值区间//在本题中,我们将一段区间 与 一颗左偏树等同:将求调整给定数列 vi 为不减序列的代价 与 求取数列 bi 等同 1 #include"iostream" 2 #include"cstd

HDU 4670 Cube number on a tree ( 树的点分治 )

题意 : 给你一棵树 . 树的每一个结点都有一个权值 . 问你有多少条路径权值的乘积是一个全然立方数 . 题目中给了你 K 个素数 ( K <= 30 ) , 全部权值都能分解成这k个素数 思路 : 一个全然立方数的素因子个数都是三的倍数 , 所以我们仅仅要求各个素数的个数即可了 , 而且我们仅仅关心个数对三的余数 所以我们能够用一个 长整形来表示每一个结点到根的各个素因子的个数( 三进制压缩 ) . 只是由于用位运算会快一点 , 所以我用了四进制.即每两位表示一个素因子的个数 . 中间合并的时

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结点进行染色. 理解如下: 假设在上述情况下先对其他结点染色,在

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求出这颗树的欧拉回路,以及每个点的