【spfa】闯关

问题描述

蒜头君在玩一个很好玩的游戏,这个游戏一共有至多 100 个地图,其中地图 1 是起点,房间 n 是终点。有的地图是补给站,可以加 ki点体力,而有的地图里存在怪物,需要消耗 ki 点体力,地图与地图之间存在一些单向通道链接。
蒜头君从 1 号地图出发,有 100 点初始体力。每进入一个地图的时候,需要扣除或者增加相应的体力值。这个过程持续到走到终点,或者体力值归零就会 Game Over。不过,他可以经过同个地图任意次,且每次都需要接受该地图的体力值。
输入格式
第 1 行一个整数 n (n≤100)。
第 2 ~ n+1 行,每行第一个整数表示该地图体力值变化。接下来是从该房间能到达的房间名单,第一个整数表示房间数,后面是能到达的房间编号。
输出格式
若玩家能到达终点,输出Yes,否则输出No。
样例输入
5
0 1 2
-60 1 3
-60 1 4
20 1 5
0 0
样例输出

No


大致思路:

因为有负权,所以打算用spfa。

思路就是求源点结点1到终点的最长路,看看到终点的最大体力值有没有小于0,有则到不了。注意源点的dis[1]设置为100。

这里和spfa模板的不同之处在于这不是按边带权的,而是按点带权的,所以这里没有将权值w定义在边的struct里,而是另外设了一个数组专门存w。

代码:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int MAX_N=105;
const int MAX_M=10000;
struct 
{
	int e;int next;
}e[MAX_M]; 
int p[MAX_N]; //记得要初始化为-1 
int cnt=0;
int w[MAX_N]; //根据本题题意,权值不是对边,所以w不写在e里 
void add(int ss,int ee)
{
	e[cnt].e=ee;
	//e[cnt].w=w;
	e[cnt].next=p[ss];
	p[ss]=cnt;
	cnt++;
}
void add2(int s,int e)
{
	add(s,e);
	add(e,s);
}
//求最长路
int dis[MAX_N];  //注意要先初始化为-inf! 
bool isin[MAX_N]; //队列的标记数组
queue<int> q;
void spfa_MAX(int s)
{
	dis[s]=w[s]+100;  //根据题意,刚出发是有初始体力的 
	isin[s]=true;
	q.push(s);
	while(q.empty()==false)
	{
		int x=q.front();
		q.pop();
		isin[x]=false;
		for(int i=p[x];i!=-1;i=e[i].next)
		{
			int y=e[i].e;
			if(dis[x]+w[y]>dis[y] && dis[x]+w[y]>0)
			{
				dis[y]=dis[x]+w[y];
				if(isin[y]==false)
				{
					isin[y]=true;
					q.push(y);
				}
			}
		}
	}
} 

int main()
{
	memset(p,-1,sizeof(p));
	memset(dis,-1e6,sizeof(dis));
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int a;
		cin>>a;
		w[i]=a;
		int k;
		cin>>k;
		while(k--)
		{
			int b;
			cin>>b;
			add2(i,b);
		}
	}
	spfa_MAX(1);
	if(dis[n]<0) cout<<"No";
	else	cout<<"Yes";
	return 0;
}

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38033475/article/details/79946736
个人分类: 蓝桥杯
上一篇【SPFA单源最短路】知识点讲解 + 与dijkstra比较
下一篇【签到题】吃苹果
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭