https://vjudge.net/problem/POJ-1860
题意:
有多种货币,可以交换,有汇率并且需要支付手续费,判断是否能通过不断交换使本金变多。
思路:
Bellman-Ford算法。
在此之前对贝尔曼-福特算法没怎么了解,当边的权值存在负值的情况下,就可以使用贝尔曼-福特算法。
这个算法主要分为三个部分:
1、首先初始化,和Dijkstra一样,记录原点到各个点的距离,将原点的值设为0,其余点设为无穷大。
2、有n个点的情况下,最多只需要遍历n-1次,每次遍历所有边,进行松弛计算。也就是if(d(v)>d(u)+w(u,v)),d(v)=d(u)+w(u,v)。
3、第三部分就是用来检测是否存在复环的,最后再遍历一次所有边,如果存在d(v)>d(u)+w(u,v),则说明存在负环。
回到这道题,这道题目的话就是求一个最大路径,也就是松弛计算的时候计算更大值,最后判断是否存在正环,如果存在,则说明是可以变多的。
1 #include<iostream> 2 #include<algorithm> 3 #include<string> 4 #include<cstring> 5 #include<set> 6 #include<map> 7 using namespace std; 8 9 const int maxn = 200 + 5; 10 11 int n, m, s; //货币总数、兑换点数量、有第s种货币 12 double v; //持有的s货币本金 13 int cnt; 14 15 double d[maxn]; 16 17 struct node 18 { 19 int a; 20 int b; 21 double rate; 22 double c; 23 }edge[maxn]; 24 25 bool bellman_ford() 26 { 27 memset(d, 0, sizeof(d)); 28 d[s] = v; 29 30 bool flag; 31 for (int i = 1; i <= n - 1; i++) 32 { 33 flag = false; 34 for (int j = 0; j < cnt; j++) 35 { 36 if (d[edge[j].b] < (d[edge[j].a] - edge[j].c)*edge[j].rate) 37 { 38 d[edge[j].b] = (d[edge[j].a] - edge[j].c)*edge[j].rate; 39 flag = true; 40 } 41 } 42 if (!flag) break; 43 } 44 45 for (int j = 0; j < cnt;j++) 46 if (d[edge[j].b] < (d[edge[j].a] - edge[j].c)*edge[j].rate) 47 return true; 48 return false; 49 } 50 51 int main() 52 { 53 //freopen("D:\\txt.txt", "r", stdin); 54 int a, b; 55 double rab, cab, rba, cba; 56 while (~scanf("%d%d%d%lf", &n, &m, &s, &v)) 57 { 58 cnt = 0; 59 for (int i = 0; i < m; i++) 60 { 61 scanf("%d%d%lf%lf%lf%lf", &a, &b, &rab, &cab, &rba, &cba); 62 edge[cnt].a = a; 63 edge[cnt].b = b; 64 edge[cnt].rate = rab; 65 edge[cnt++].c = cab; 66 edge[cnt].a = b; 67 edge[cnt].b = a; 68 edge[cnt].rate = rba; 69 edge[cnt++].c = cba; 70 } 71 if (bellman_ford()) 72 printf("YES\n"); 73 else 74 printf("NO\n"); 75 } 76 return 0; 77 }