题解:
我们可以令f[i]f[i]表示杀死i怪兽的最小代价。
f[i]=min(k[i],s[i]+∑(f[j]))f[i]=min(k[i],s[i]+∑(f[j])),jj为受到物理攻击后分裂成的所有怪兽。
我们发现直接dpdp是有后效性的,我们可以用SPFASPFA来做这个dpdp。
用两个数组每次更新差值就好了。
Code:Code:
#include<bits/stdc++.h>
#define ll long long
#define N 300005
using namespace std;
struct edge
{
int vet,next;
}edge[N<<2];
int head[N],tot=0;
void add_edge(int u,int v)
{
edge[++tot].vet=v;
edge[tot].next=head[u];
head[u]=tot;
}
vector<int>vet[N];
ll f[N],s[N],vis[N];
int n,r;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&s[i],&f[i]);
int w;
scanf("%d",&w);
for(int j=1;j<=w;j++)
{
int r;
scanf("%d",&r);
add_edge(i,r);
vet[r].push_back(i);
}
}
queue<int>Q;
for(int i=1;i<=n;i++)
{
Q.push(i);
vis[i]=1;
}
while(!Q.empty())
{
int u=Q.front();
Q.pop();
vis[u]=0;
ll tmp=s[u];
for(int i=head[u];i;i=edge[i].next)
tmp+=f[edge[i].vet];
if(tmp>=f[u])continue;
f[u]=tmp;
for(int i=0;i<vet[u].size();i++)
if(!vis[vet[u][i]])
{
vis[vet[u][i]]=1;
Q.push(vet[u][i]);
}
}
printf("%lld\n",f[1]);
return 0;
}