题目描述:
雾。
题目分析:
先写出 DP 方程
f[i]=min(k[i],s[i]+∑Rj=1f[toj])
f
[
i
]
=
m
i
n
(
k
[
i
]
,
s
[
i
]
+
∑
j
=
1
R
f
[
t
o
j
]
)
也就是可以直接用膜法攻击杀死怪兽,或者是普通攻击杀死怪兽以后杀死产生的新怪兽
暴力转移肯定不行
观察一下上面的式子
若f[i]成功更新了,那么就可能会对可以产生他的怪兽的f[j]产生贡献
那么我们就需要把可以产生i的怪兽全部更新一遍
是不是很像SPFA
我们只需要按照SPFA的方法即可
题目链接:
Ac 代码:
#include <cstdio>
#include <iostream>
#include <queue>
#define int long long
const int maxm=201000;
int dis[maxm];
int head[2][maxm],to[2][maxm*10],net[2][maxm*10],cnt[2];
bool vis[maxm];
std::queue <int> dl;
int n,a[maxm];
void addedge(int u,int v,int f)
{
cnt[f]++;
to[f][cnt[f]]=v,net[f][cnt[f]]=head[f][u],head[f][u]=cnt[f];
}
void SPFA()
{
for(int i=1;i<=n;i++) dl.push(i),vis[i]=1;
while(!dl.empty())
{
int now=dl.front();
dl.pop();
vis[now]=0;
int tmp=a[now];
for(int i=head[0][now];i;i=net[0][i])
tmp+=dis[to[0][i]];
if(tmp>=dis[now]) continue;
dis[now]=tmp;
for(int i=head[1][now];i;i=net[1][i])
if(!vis[to[1][i]]) vis[to[1][i]]=1,dl.push(to[1][i]);
}
}
main()
{
scanf("%lld",&n);
for(int i=1,r;i<=n;i++)
{
scanf("%lld%lld%lld",&a[i],&dis[i],&r);
for(int j=1;j<=r;j++)
{
int x;
scanf("%lld",&x);
addedge(i,x,0),addedge(x,i,1);
}
}
SPFA();
printf("%lld\n",dis[1]);
return 0;
}