链接
分析
昨天(今天)coderforces good bye2020上面的题目,起初的想法是dfs,结果直接超时,后来又模拟了一下过程,发现是出度统计。即一个节点最多被使用的次数等于它的出度(即与他相连的节点个数),在可以选择的节点中,优先选择权值最大的节点。我们把w[i]的和先求出来,得到sum,相当于每个节点都用了一次,然后在通过出度将剩下可以使用的节点记录下来,排序一下即可。实际上就是找规律,简单贪心一下。
code
#include <algorithm>
#include <cstring>
#include <cctype>
inline int read(){
int x = 0; char ch = getchar();
while (!isdigit(ch)){ch = getchar();}
while (isdigit(ch)){x = (x<<1)+(x<<3)+(ch^48); ch = getchar();}
return x;
}
inline void write(long long x){
if (x < 0) putchar('-'), x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
const int N = 1e5 + 10;
int t, n, cnt;
int w[N], val[N];
int out[N];
void solve(){
long long res = 0;
n = read(), cnt = 0;
memset(out, 0, sizeof out);
memset(val, 0, sizeof val);
for (int i = 1; i <= n; ++i) res += w[i] = read();
for (int i = 1, x, y; i < n; ++i) {
x = read(), y = read();
++out[x]; ++out[y];
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j < out[i]; ++j)
val[++cnt] = w[i];
std::sort(val + 1, val + 1 + cnt);
for (int i = cnt + 1; i >= 1; i--) {
res += val[i];
write(res), putchar(' ');
}
putchar('\n');
}
int main() {
t = read();
while (t--)
solve();
return 0;
}
不知不觉2020也快要过去啦。