/**
* poj1860 Bellman_Ford
* 是一个逆向使用bellman_ford算法的题目。原来单源最短路径的算法是避免负的环路,这里我们反过来,是求正的环路
* BF算法的核心思想就是,单源最短路径如果存在,即不存在环路,那么在N个点的图中,我N-1次松弛一定可以存在最短路径.否则负向环路就会出现
* 用在这里就是,N个点的图中,N-1次松弛一定可以找到潜在的正向环路
* 因为我是从原点开始,而每条边都是双向的,那如果正向环路存在,我在正向环路里走足够多个圈,总可以实现到原点的正向回环
* 这样初始化的时候我们把其他路径边都置为最小的0,依各个边去松弛,对于a->b的兑换,如果有v个a,假如按照rab*(va-cab)计算出来的值比原有的vb大,那么就更新vb
* 最后像BF算法那样判断有无正向回环就行了
*/
#include <cstdio>
#include <cstring>
int n,m,s,idx;
double v;
struct exchange{
int a;
int b;
double rate;
double fee;
}ec[101*101];
double money[101];
bool bellman_ford(){
bool flag;
memset(money,0,sizeof(money));
money[s] = v;
for(int i=0;i<n;++i){
flag = false;
//以j为条件边松弛其他边
for(int j=0;j<idx;++j){
if(money[ec[j].a]==0) continue;
if(money[ec[j].b] < (money[ec[j].a] - ec[j].fee)*ec[j].rate){
money[ec[j].b] = (money[ec[j].a] - ec[j].fee)*ec[j].rate;
flag = true;
}
}
if(!flag){
break;
}
}
for(int j=0;j<idx;++j){
if(money[ec[j].b] < (money[ec[j].a] - ec[j].fee)*ec[j].rate){
money[ec[j].b] = (money[ec[j].a] - ec[j].fee)*ec[j].rate;
return true;
}
}
return false;
}
int main(){
scanf("%d%d%d%lf",&n,&m,&s,&v);
int a,b;
double rab,cab,rba,cba;
idx = 0;
while(m--){
scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba);
ec[idx].a = a;
ec[idx].b = b;
ec[idx].rate = rab;
ec[idx++].fee = cab;
ec[idx].a = b;
ec[idx].b = a;
ec[idx].rate = rba;
ec[idx++].fee = cba;
}
if(bellman_ford()){
printf("YES\n");
}
else{
printf("NO\n");
}
return 0;
}
poj1860 Bellman-Ford
最新推荐文章于 2020-01-12 14:58:38 发布