过年了,写点水题熟练算法的使用,开心开心。
题意:某个人手中有B类货币,他想投机取巧,请你帮忙判断从所持货币出发,最后兑换回该货币是否能够使得所持货币有所增加。
更高效的思路:
SPFS某个值被更新超过n-1次说明存在可以无限更新的回路。
但是未免大材小用,用bellman-ford就能很简单地写出来,看起来有50行,但实际代码量非常小。
#include <cstdio>
#include <cstring>
#include <vector>
#define DEB puts("debug")
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define TRV(_i,_V) for(int _i=(_V).size()-1;_i+1;_i--)
#define PB push_back
#define all(x) x.begin(),x.end()
using namespace std;
//边结构体
struct e{
int u,v;double r,c;
};
//边集
vector<e> E;
//最"长"路
double dist[105];
int main(){
//n,m题目有描述
//a,b:边端点
//s(start):起点,v(val):起点值,newv:可能的松弛距离
//released:本次迭代是否松弛过。
int n,m,a,b,s;e tem;double newv,v;bool released;
while(~scanf("%d%d%d%lf",&n,&m,&s,&v)){
//初始化
memset(dist,0,sizeof(dist));
E.clear();
dist[s]=v;
//读入数据
F(i,m){
scanf("%d%d",&a,&b);
tem.u=a;tem.v=b;
scanf("%lf%lf",&tem.r,&tem.c);
E.PB(tem);
tem.u=b;tem.v=a;
scanf("%lf%lf",&tem.r,&tem.c);
E.PB(tem);
}
//bellman-ford
F(i,n){
released=false;
TRV(j,E){
if(dist[E[j].v]<(newv=(dist[E[j].u]-E[j].c)*E[j].r)){
dist[E[j].v]=newv;
released=true;
}
}
if(!released)break;
}
//判环
released=false;
TRV(j,E){
if(dist[E[j].v]<(newv=(dist[E[j].u]-E[j].c)*E[j].r))released=true;
//一旦松弛更新次数就>=n次
if(released)break;
}
//是否松弛
puts(released?"YES":"NO");
}
}