传送门:13th Labour of Heracles 优先队列
题目描述
You've probably heard about the twelve labors of Heracles, but do you have any idea about the thirteenth? It is commonly assumed it took him a dozen years to complete the twelve feats, so on average, a year to accomplish every one of them. As time flows faster these days, you have minutes rather than months to solve this task. But will you manage?
In this problem, you are given a tree with n weighted vertices. A tree is a connected graph with n−1 edges.
Let us define its k -coloring as an assignment of k colors to the edges so that each edge has exactly one color assigned to it. Note that you don't have to use all k colors.
A subgraph of color x consists of these edges from the original tree, which are assigned color x , and only those vertices that are adjacent to at least one such edge. So there are no vertices of degree 0 in such a subgraph.
The value of a connected component is the sum of weights of its vertices. Let us define the value of a subgraph as a maximum of values of its connected components. We will assume that the value of an empty subgraph equals 0 .
There is also a value of a k -coloring, which equals the sum of values of subgraphs of all k colors. Given a tree, for each k from 1 to n−1 calculate the maximal value of a k -coloring.
输入格式
In the first line of input, there is a single integer t ( 1≤t≤105 ) denoting the number of test cases. Then t test cases follow.
First line of each test case contains a single integer n ( 2≤n≤105 ). The second line consists of n integers w1,w2,…,wn ( 0≤wi≤109 ), wi equals the weight of i -th vertex. In each of the following n−1 lines, there are two integers u , v ( 1≤u,v≤n ) describing an edge between vertices u and v . It is guaranteed that these edges form a tree.
The sum of n in all test cases will not exceed 2⋅105 .
输出格式
For every test case, your program should print one line containing n−1 integers separated with a single space. The i -th number in a line should be the maximal value of a i -coloring of the tree.
题意翻译
给定一棵树。点有点权。
定义一种颜色 x 的同色子图为所有颜色为 x 的边及其顶点形成的同色子图。
一个同色连通块的权值定义为该连通块的点权和。
一个同色子图的权值定义为子图内所有同色连通块的权值的最大值。
一种染色方案的权值定义为所有颜色的同色子图的权值和。
对于每个 i∈[1,n−1]∩Z,求染 i 种颜色不同染色方案的权值的最大值。颜色不必用完。
题解
思路:由于一个颜色只能占一个连通块,可以知道只有非叶子节点的权重才能影响染色结果,我们将非叶子节点的权重按照从大到小的顺序排序,然后递减地加入到总值 ans 中,并输出当前的染色方案的最大值。整体思路就是根据题目给出的染色方案的定义,通过逐步将非叶子节点的权重加入到总值中,找到最优的染色方案,然后输出即可。
-
数据结构定义:
- 定义了一个结构体
Edge
,其中包含了节点的degree
(度数)和val
(值)。degree
用于记录节点的连接数量,val
是节点的原始值。
- 定义了一个结构体
-
输入处理:
- 读取测试案例的数量
t
。 - 逐个处理每个测试案例:
- 读取节点数
n
,初始化sum
为 0,并清空优先队列q
。 - 循环读取每个节点的值,并计算所有节点的和
sum
。同时,将每个节点的degree
初始化为0。
- 读取节点数
- 读取测试案例的数量
-
图的构建:
- 接着,读取
n-1
条边,从而构建一棵树。对于每条边(a, b)
,增加节点a
和b
的degree
值,表示这两个节点之间有一条连接。
- 接着,读取
-
优先队列填充:
- 遍历每个节点,如果节点的
degree
大于等于2,说明该节点连接了多个其他节点。在这种情况下,将该节点的值e[i].val
放入优先队列q
,直到degree
降到1。这样做的目的是把值高的节点优先处理。
- 遍历每个节点,如果节点的
-
结果输出:
- 首先输出总和
sum
。 - 然后,从优先队列中取出最大的值(表示当前节点的值),累加到
sum
,并输出更新后的sum
。循环范围是从2到n
,实际上输出的是从第2个到第(n-1)个节点的这些累加操作的结果。 - 最后,以换行结束当前测试案例的输出。
- 首先输出总和
#include <iostream>
#include <queue>
using namespace std;
#define ll long long
struct Edge{
int degree=0,val=0;
}e[200005];
priority_queue<int>q;
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
ll sum=0;
while(!q.empty())q.pop();
for(int i=1;i<=n;i++){
cin>>e[i].val;
e[i].degree=0;
sum+=e[i].val;
}
for(int i=1;i<n;i++){
int a,b;
cin>>a>>b;
e[a].degree++;
e[b].degree++;
}
for(int i=1;i<=n;i++){
if(e[i].degree>=2){
while(e[i].degree>=2){
q.push(e[i].val);
e[i].degree--;
}
}
}
cout<<sum<<" ";
for(int i=2;i<n;i++){
sum+=q.top();
q.pop();
cout<<sum<<" ";
}
cout<<endl;
}
return 0;
}