[tyvj 1176]火焰巨魔的惆怅

7 篇文章 0 订阅
1 篇文章 0 订阅

背景

TYVJ2月月赛第一道

巨魔家族在某天受到了其他种族的屠杀,作为一个英雄,他主动担任了断后的任务,但是,在巨魔家族整体转移过后,火焰巨魔却被困住了,他出逃的方式也只有召唤小火人这一种方式,所以请你帮助他。

描述

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

输入格式

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

输出格式

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

测试样例1

输入

5 4 
1 2 -3 
1 3 -6 
3 4 1 
4 5 -9

输出

4

备注

初始小火人为4个,到3点剩2个,到4变成5个,到5剩1个。

所以初始最少为4,更少的小火人是不足以走到5号点位的。from wsd  TYVJ月赛出题组


题解


从最后一个点倒着想 设最后一个点剩一个然后倒着推


把边反过来 加减反过来 乘变成除 当一个点i的d[i]小于1时 把他变成1 注意除法向上取整


//http://new.tyvj.cn/p/1176
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define N 50001
#define inf 1<<29
using namespace std;
int n,m,head[N],d[N];
int flag[N],cnt;
queue<int>q;
struct node{int to,w,next;}e[100001];
void insert(int x,int y,int z){
	e[++cnt].to=y;e[cnt].w=z;e[cnt].next=head[x];head[x]=cnt;
}
int get(int n){//向上取整 因为只有向上才可以满足条件 不一定最优解最后一个点剩下的就是1 
	if(n%2!=0)n++;
	return n/2;
}
void spfa(){
	for(int i=1;i<=n;i++)
		d[i]=inf;
	d[n]=1;//注意 最后一个点最少剩一个 
	flag[n]=1;
	q.push(n);
	while(!q.empty()){
		int k=q.front();
		q.pop();flag[k]=0;
		for(int i=head[k];i;i=e[i].next){
			int kk=e[i].to;
			if(d[kk]>get(d[k]+e[i].w)){
				d[kk]=get(d[k]+e[i].w);
				if(d[kk]<1)d[kk]=1; 
				if(!flag[kk]){
					flag[kk]=1;
					q.push(kk);
				}
			}
		} 
	}
}
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(y,x,-z);	//设到终点的时候剩一个 然后倒着做 操作反过来 加变减减变加 
	}
	spfa();
	printf("%d",d[1]);
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值