题目描述:
还是货币兑换的题,想找是否货币经过无数次兑换后是否会升值。兑换边符合(兑换货币值-兑换费用)*兑换率。
解题思路:
典型的bellman ford。但是忘了。。。。
复习下bellman-ford
首先是带负权值边的图,对于这样的图,如果存在负权回路是没法用djs等求最短路径的,因为每次更新不能确定的最短路径的点(可能由其他大权值的边+一条负权值的边重新更新得到更小)。
那么,对于包含复权回路的图,如何判断一个图是否存在负权回路能否计算出最短路径呢?bellman-ford就是解决介个问题滴。
判断方式就是:
我们知道如果这个图不存在负权回路的话,每做一次全部边的松弛操作(松弛操作就是判断 src->j 的长度是否大于 src->i+i->j的长度),是可以确定至少一个点的(因为只要没负权回路,就是指存在最短路径的说法,那么因为存在一个原始的出发点作为当前最短,肯定松弛过后肯定能有个点也达到了自己的最短情况)。
也就是说,如果做了n-1次的全部边松弛操作之后,就确定了所有点的最短路径值。如果做第n次全部边松弛操作的时候,还有点的最短值会被更新,则说明图里是存在负权回路的。
因此bellman ford算法是做n次边松弛操作,每次边松弛判断的是m条边。因此算法复杂度为O(nm)。
代码:
#include
#include
#define E 10001
#define N 101
typedef struct{
int s, e;
double w, c;
}EDGE;
int n,m,s;
double v, D[N];
EDGE edges[E];
main(){
int i, j, flag;
scanf(“%d %d %d %lf”, &n, &m, &s, &v);
for(i=1;i<=m;i++){
scanf(“%d %d %lf %lf %lf %lf”,&edges[2*i-1].s,&edges[2*i-1].e, &edges[2*i-1].w, &edges[2*i-1].c, &edges[2*i].w, &edges[2*i].c);
edges[2*i].s = edges[2*i-1].e;
edges[2*i].e = edges[2*i-1].s;
}
//memset(D,0,sizeof(D));
for(i=1; i<=n; i++)
D[i] = 0.0;
D[s] = v;
//bellman-ford
for(i=1;i<=n;i++){
flag = 0;
for(j=1;j<=2*m;j++){ //遍历边做松弛操作
double temp = (D[edges[j].s] – edges[j].c)*edges[j].w;
if(D[edges[j].e] < temp){
//if(D[edges[j].e] < (D[edges[j].s] – edges[j].c)*edges[j].w){
flag = 1;
// printf(“update %d. former = %lf, later = %lf\n”,edges[j].e, D[edges[j].e], (D[edges[j].s] – edges[j].c)*edges[j].w);
D[edges[j].e] = (D[edges[j].s] – edges[j].c)*edges[j].w;
}
}
if(0 == flag)
break;
}
if(1 == flag){
printf(“YES\n”);
}else{
printf(“NO\n”);
}
system(“pause”);
return 0;
}