题目地址
2
7
13 20 1 20 6 9 8
1 2
1 3
2 4
2 5
3 6
5 7
4
1 17 13 4
1 2
1 3
3 4
输出
27
5
思路看此
#include
#include
#include
#include
using namespace std;
#define int long long
const int N = 2e5 + 10;
int e[N<<1],ne[N<<1],h[N],idx;
int f[N][3];
int a[N];
bool has[N];
void add(int a,int b)
{
e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
void dfs(int u,int fa)
{
f[u][0] = a[u];
int sum = 0;
int mincost = 1e10;
for(int i = h[u];~i;i = ne[i])
{
int v = e[i];
if(v == fa) continue;
dfs(v,u);
int t = min(f[v][0],f[v][2]);//无父结点覆盖的最小花费方案
// 选取当前结点
f[u][0] += min(t,f[v][1]);
// 父结点覆盖 u 的情况
f[u][1] += t;
// 子节点覆盖 u 的情况
f[u][2] += t;
if(f[v][0] < f[v][2])
sum++;
else
mincost = min(mincost,f[v][0]-f[v][2]);
}
if(!sum)
f[u][2] += mincost;
}
void solve()
{
int n;
cin >> n;
// 初始化
memset(h,-1,sizeof h);
memset(has,0,sizeof has);
memset(f,0,sizeof(f));
idx = 0;
for(int i = 1;i <= n;i ++ ) cin >> a[i];
for(int i = 1;i <= n - 1;i ++ )
{
int u,v;
cin >> u >> v;
add(u,v);
add(v,u);
has[v] = true;
}
int root = -1;
for(int i = 1;i <= n;i ++ )
if(!has[i]) root = i;
dfs(root,-1);
cout << min(f[root][0],f[root][2]) << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while(T -- ) solve();
}