没什么卵用的目录
题目地址
AC代码
#include <iostream>
using namespace std;
int main() {
int n,t,have;
double money;
cin>>n>>t>>have>>money;
int s[2*t],v[2*t];
double c[2*t],r[2*t],dis[n+1];
for (int i = 0; i < 2*t; i+=2) {
int huobi1,huobi2;
cin>>huobi1>>huobi2;
double rab,cab,rba,cba;
cin>>rab>>cab>>rba>>cba;
s[i]=huobi1,v[i]=huobi2,r[i]=rab,c[i]=cab;
s[i+1]=huobi2,v[i+1]=huobi1,r[i+1]=rba,c[i+1]=cba;
}
for (int j = 1; j <=t ; ++j) {
dis[j]=0;
}
dis[have]=money;
for (int k = 0; k < n; ++k) {
for (int i = 0; i < 2*t; ++i) {
if(dis[v[i]]<(dis[s[i]]-c[i])*r[i])dis[v[i]]=(dis[s[i]]-c[i])*r[i];
}
}
int boo = 0;
for (int k = 0; k < n; ++k) {
for (int i = 0; i < 2*t; ++i) {
if(dis[v[i]]<(dis[s[i]]-c[i])*r[i]){
boo = 1;
break;
}
}
}
if(boo)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
return 0;
}
题解和题目思路
这题使用的是更改过后的Bellman-Ford算法,将原有的查找最短路径以及负权值回环转化为了查找最长路径及正权值回环。
Bellman-Ford算法的实现可以看下面,这里先讲题目的思路。
本题的dis[]数组存放的是由一开始持有的货币在经过k次松弛之后得到的当前种类货币的金额。
按照惯例,在松弛完n-1次之后,如果还存在可以松弛的情况,那么我们就可以判断这里存在回环。本题就意味着一定存在正回环,可以使得货币越换越多,钱生钱 //滑稽
如果存在回环,则输出YES,否则就输出NO
原始的Bellman-Ford算法实现
#include <iostream>
using namespace std;
int main() {
int t,n,b,e;
cin>>t>>n>>b>>e; //初始化点的数目,边的数目,起点和终点编号
int s[n],v[n],w[n],dis[t+1];
for (int i = 0; i < n; ++i) {
cin>>s[i]>>v[i]>>w[i]; //输入边的信息,如果是无向图请自行添加多余的边
}
for (int k = 0; k <= t; ++k) { //初始化距离数组
dis[k]=6666;
}
dis[b]=0;
for (int j = 0; j < t; ++j) { //进行松弛,查找最短路径
for (int i = 0; i < n; ++i) {
if(dis[v[i]]>dis[s[i]]+w[i])dis[v[i]]=dis[s[i]]+w[i];
}
}
int boo = 0;
for (int j = 0; j < t; ++j) { //判断是否存在负权回环
for (int i = 0; i < n; ++i) {
if(dis[v[i]]>dis[s[i]]+w[i]){
boo = 1;
break;
}
}
}
if(boo)cout<<"不存在最短路径";
else cout<<dis[e];
return 0;
}