//2484K 16MS G++
#include <stdio.h>
#include <string.h>
#define MAX_EXCHANGE_POINT 300
#define MAX_CURRENCY 300
struct ExchangeDetail {
int A;
int B;
double R;
double C;
};
typedef struct ExchangeDetail ExchangeDetail;
ExchangeDetail currencyExchangeInfo[MAX_CURRENCY][MAX_CURRENCY];
ExchangeDetail exchangeRelation[MAX_CURRENCY];
int exchangeRelationNum = 0;
double exchangeQuanitity[MAX_CURRENCY];
#define MINUS_INF -999999
int exchangePointNum;
int currenciesNum;
int curCurrency;
double number;
int edgeNum;
char BF() {
// printf("BF\n");
for (int i = 1; i <= currenciesNum; i++) {
exchangeQuanitity[i] = MINUS_INF;
}
exchangeQuanitity[curCurrency] = number;
for (int i = 1; i <= currenciesNum - 1; i++) {
for (int j = 1; j <= edgeNum; j++) {
int A = exchangeRelation[j].A;
int B = exchangeRelation[j].B;
double R = exchangeRelation[j].R;
double C = exchangeRelation[j].C;
double quanityAfterExchanged;
if (exchangeQuanitity[A] == MINUS_INF) { // no need to relax
quanityAfterExchanged = MINUS_INF; // MINUS_INF + any is still MINUS_INF
} else {
quanityAfterExchanged = (exchangeQuanitity[A] - C) * R;
}
double orginal = exchangeQuanitity[B];
if (quanityAfterExchanged > orginal) { // can relax;
exchangeQuanitity[B] = quanityAfterExchanged;
}
}
}
for (int i = 1; i <= edgeNum; i++) {
int A = exchangeRelation[i].A;
int B = exchangeRelation[i].B;
double R = exchangeRelation[i].R;
double C = exchangeRelation[i].C;
double quanityAfterExchanged;
if (exchangeQuanitity[A] == MINUS_INF) { // no need to relax
quanityAfterExchanged = MINUS_INF;
} else {
quanityAfterExchanged = (exchangeQuanitity[A] - C) * R;
}
double orginal = exchangeQuanitity[B];
if (quanityAfterExchanged > orginal) { // can relax;
return 1;
}
}
// printf("BF end\n");
return 0;
}
int main() {
memset(currencyExchangeInfo, 0, sizeof(currencyExchangeInfo));
memset(exchangeRelation, 0, sizeof(exchangeRelation));
exchangeRelationNum = 0;
edgeNum = 0;
scanf("%d %d %d %lf", ¤ciesNum, &exchangePointNum, &curCurrency, &number);
for(int i = 0; i < exchangePointNum; i++) {
int currencyA;
int currencyB;
double RAB;
double CAB;
double RBA;
double CBA;
scanf("%d %d %lf %lf %lf %lf", ¤cyA, ¤cyB, &RAB, &CAB, &RBA, &CBA);
currencyExchangeInfo[currencyA][currencyB].R = RAB;
currencyExchangeInfo[currencyA][currencyB].C = CAB;
currencyExchangeInfo[currencyB][currencyA].R = RBA;
currencyExchangeInfo[currencyB][currencyA].C = CBA;
exchangeRelation[++edgeNum].A = currencyA;
exchangeRelation[edgeNum].B = currencyB;
exchangeRelation[edgeNum].R = RAB;
exchangeRelation[edgeNum].C = CAB;
exchangeRelation[++edgeNum].A = currencyB;
exchangeRelation[edgeNum].B = currencyA;
exchangeRelation[edgeNum].R = RBA;
exchangeRelation[edgeNum].C = CBA;
}
char res = BF();
if (res) {
printf("YES\n");
} else {
printf("NO\n");
}
}
2484K 16MS G++
典型的bellman_ford运用,不过松弛的条件变了,
一开始想偏了,不知道该怎样描述图里面边的含义,后来发现想多了,每条边就
直接按照题目的含义来就可以了(及兑换的rate和commission)重要的是点的含义,每个点应该代表的含义的是
Nick带的currency(S) 兑换该点对应的currency 所能兑换的最大量。
并且题目给的input保证了Nick一定可以在兑换数次以后,还能重现兑换回最开始的currency(因为该图是一个连通图,一个点到另一个点只要有去的路,就有回来的路,所以不存在不能返回的情况,及任何情况下都可以兑换回去)。
那么要想让Nick的资本能够升值,必须在这个图中存在一个正权回路(每循环一次该回路,因为是正权回路,所以可以总资产会增加)。
那么其实只要检查图里是否存在这样的正权回路就可以了,那么判断是否有回路,就要用BF算法了,
不同的是,算导中举得BF应用场景是经典的最短路场景,而在这里却貌似要求的是最长路,、
其实是不冲突的,所谓最短/最长/以及最XX其实是针对某个条件来说的,BF求的其实是在 这个条件或者说维度上最接近(或者可以说等于)该维度极限 的路径。
这其实才是BF的精髓,理解了这个,才能对BF题的变种进行求解,不然会一直局限于最短路这个概念。
有了这个,剩下就是写BF code了,非常简单,
要注意的是,最开始给每个node 的 dis[]赋初值时, dis[S] 不应该是最短路场景中的0,而应该是Nick初始拥有的S的数量(和0虽然数字不一样,但在含义上是一样的,
都代表了起始点的最极限状态, 最短路中,起始点的距离起始点当然是0, 而在本场景中,在起始点,没有经过任何兑换,那么必然S的数量就是起始值)。
还有就是其他Node的dis[]初始化为了无限小(因为此时还没有开始兑换),因为在实际编程中,不可能真有一个无限小,所以一般是定义一个-999999之类的数,
注意的是,这个无限小在和其他数运算以后,还应该是无限小(即还是-999999),否则可能会出现 -999997...之类的数,有时候会引起算法错误。
因此,要注意这一点,只要有无限小参与了运算,结果还应该是无限小.
最后就就是判断BF返回值了,false的话就是YES,别搞混了.