解析:
某种药水三种来源:
1.免费无限量供应
2.用单价购买
3.合成
所以首先记录所有药水的价格,并且记录合成途径,每次DFS记忆化搜索,保存以及搜过的药水的最小价格。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll t,n,k,a[N],f[N],x,y;
vector<int>e[N];
ll dfs(int x){
if(f[x]!=-1) return f[x];
ll sum=0;
for(int i=0;i<e[x].size();i++){
sum+=dfs(e[x][i]);
}
return f[x]=min(sum,a[x]);
}
int main(){
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
e[i].clear();
f[i]=-1;
}
for(int i=1;i<=k;i++){
scanf("%d",&x);
a[x]=0;
}
for(int i=1;i<=n;i++){
ll sum=0;
scanf("%lld",&x);
for(int j=0;j<x;j++){
scanf("%lld",&y);
if(!a[i]) continue;
e[i].push_back(y);
}
if(x==0) f[i]=a[i];
}
for(int i=1;i<=n;i++){
printf("%lld ",dfs(i));
}
puts("");
}
return 0;
}