tyvj 火焰巨魔的惆怅

描述 Description

我们把火焰巨魔所处的位置抽象成一张有向图,他的位置就是1号点位,目的就是走到第N号点位,因为小火人会裂嘛,所以我们可以看做每走一条路,小火人的数量都会加倍,而每条路上的敌人有多强,会消耗多少小火人c[i]也会给出(c[i]为负值);当然有些时候路上也会遇到魔法泉之类的东西,这时候就可以补充一些小火人咯(c[i]为正值)。如果小火人死光了,那么火焰巨魔也就可以看做是挂了,毕竟智力型英雄就是脆啊。希望你帮助火焰巨魔用最少的初始小火人逃离这次屠杀。

输入格式 InputFormat
第一行两个数N(<=50000),M(<=100000)表示点位数与边数。
一下M行,每行三个数a,b,c表示a,b两点间的边权是c(|c|<=10000)

输出格式 OutputFormat
输出仅一个整数,表示最小初始小火人数。

样例输入 SampleInput 
5 4
1 2 -3
1 3 -6
3 4 1
4 5 -9
样例输出 SampleOutput 
4
数据范围和注释 Hint
初始小火人为4个,到3点剩2个,到4变成5个,到5剩1个。
所以初始最少为4,更少的小火人是不足以走到5号点位的。

题解

这道题有一点点恶心,不过还好。spfa倒着做,注意当dis[i]<1时,dis[i]=1。
代码如下
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
using namespace std;
int n,m,zz=0,head[50002];
struct bian
{int to,nx,l;} e[200002];
int q[50002],dis[50002];
bool pd[50002];
void insert(int x,int y,int z)
{
	zz++; e[zz].to=x; e[zz].l=z; e[zz].nx=head[y]; head[y]=zz;
}
int calcu(int x)
{
	if(x%2!=0) x=x+1;
    x=x/2;
    return x;
}
void spfa()
{
	memset(pd,false,sizeof(pd));
	memset(dis,127/3,sizeof(dis));
	int t=0,w=1;
	q[0]=n; pd[n]=true; dis[n]=1;
	while(t!=w)
	   {pd[q[t]]=false;
		int p=q[t],i=head[p]; t=t%n+1; 
		while(i)
		   {int s=calcu(dis[p]-e[i].l);
			if(s<dis[e[i].to])
		       {dis[e[i].to]=s;
		        if(dis[e[i].to]<1) dis[e[i].to]=1;
			    if(!pd[e[i].to])
				   {pd[e[i].to]=true; q[w]=e[i].to; w=w%n+1;}
			   }
			i=e[i].nx;
		   }
	   }
	printf("%d\n",dis[1]);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	   {int x,y,z;
	    scanf("%d%d%d",&x,&y,&z);
	    insert(x,y,z);
	   }
	spfa();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值