思路:直接对比制造这份药剂和直接买那个更好
判断特殊:
1.如果已经拥有就不用再买了
2.如果只能买,就直接买
方法:
1.dfs,因为要制造3,可能先要制造1,这样我们就dfs把条件从叶子节点全都往上传就行
优化:
1.如果之前已经知道了制造的价格,那么直接返回就行
注意点:
1.可能有些药剂不用钱,因此初始化为-1
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
#define LL long long
LL c[N],a[N], cnt[N],f[N];
vector<int> g[N];
int dfs(int x) {
if (f[x] != -1) return f[x];//之前已经知道了,直接返回
LL w = 0;
for (auto v : g[x]) {
if (v == 0) {
f[x] = c[x];//标记
return f[x];//必须买,直接返回
}
w+=dfs(v);
}
f[x] =min(w,c[x]);//取最小
return f[x];
}
void solve() {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) g[i].clear();
memset(f, -1, sizeof f);
memset(cnt, 0, sizeof cnt);
for (int i = 1; i <= n; i++) cin >> c[i];
for (int i = 1; i <= k; i++) {
int x;
cin >> x;
f[x]=0;//不用钱,直接返回
}
for (int i = 1; i <= n; i++) {
int m;
cin >> m;
for (int j = 1; j <= m; j++) {
int x;
cin >> x;
g[i].push_back(x);//记录每个药水的制造步骤
}
if (m == 0) g[i].push_back(0);
}
for (int i = 1; i <= n; i++) {
dfs(i);
}
for (int i = 1; i <= n; i++) cout << f[i] << ' ';
cout << '\n';
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}