BZOJ 3875 Ahoi2014 骑士游戏 SPFA

来源:互联网 发布:xampp使用教程 php版本 编辑:程序博客网 时间:2024/06/05 20:34

题目大意:给定n个怪物,每个怪物可以用魔法直接干掉,或者用物理攻击使其分裂为一些其他怪物,求杀掉1号怪物的最小花销

令f[i]为杀死i号怪物的最小花销,则f[i]=min(k[i],s[i]+Σf[j]) 其中j为i用物理攻击后可以分裂为的怪物

但是直接DP有后效性,因此我们用SPFA来跑这个DP即可

注意如果每次更新一个点之后都重新计算花销会T掉

改成减掉花销的差值就好了 具体写法去看代码吧- -

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 200200using namespace std;struct abcd{int to,next;}table[2002002];int head1[M],head2[M],tot;int n,m;long long f[M],g[M],phisical_attack[M],magic_attack[M];//f[x]代表最小花销//g[x]代表用物理攻击的最小花销 int q[M],r,h;bool v[M];void Add(int head[],int x,int y){table[++tot].to=y;table[tot].next=head[x];head[x]=tot;}void SPFA(){int i;while(r!=h){int x=q[(++h)%=M];v[x]=0;if(g[x]>=f[x])continue;for(i=head2[x];i;i=table[i].next){if(!v[table[i].to])v[table[i].to]=true,q[(++r)%=M]=table[i].to;g[table[i].to]-=f[x];g[table[i].to]+=g[x];}f[x]=g[x];}}int main(){int i,j,x;cin>>n;for(i=1;i<=n;i++){#ifdef ONLINE_JUDGEscanf("%lld%lld",&phisical_attack[i],&magic_attack[i]);#elsescanf("%I64d%I64d",&phisical_attack[i],&magic_attack[i]);#endifq[++r]=i;v[i]=true;scanf("%d",&m);for(j=1;j<=m;j++){scanf("%d",&x);Add(head1,i,x);Add(head2,x,i);}}for(i=1;i<=n;i++){f[i]=magic_attack[i];g[i]=phisical_attack[i];for(j=head1[i];j;j=table[j].next)g[i]+=magic_attack[table[j].to];}SPFA();cout<<f[1]<<endl;return 0;}


0 0