BZOJ 3875 Ahoi2014 骑士游戏 SPFA

13 篇文章 0 订阅

题目大意:给定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 200200
using 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_JUDGE
			scanf("%lld%lld",&phisical_attack[i],&magic_attack[i]);
		#else
			scanf("%I64d%I64d",&phisical_attack[i],&magic_attack[i]);
		#endif
		q[++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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值