就是求一条正权回环,方法在于反向使用bellman-ford。 #include <iostream> #include <cstdio> #include <cstring> using namespace std; int n; //货币种数 int m; //交换点 int s; //目前持有的货币种类 double v; //持有货币钱数 int all=0; //边数 double dis[101]; //源点到各点的权值 class exchange_point{ public: int a; int b; double r; double c; } exc[201]; bool bellman_ford() { memset(dis, 0, sizeof(dis)); dis[s] = v; // 初始源点 for (int i = 1; i <= n-1; ++i) { // |V|-1次,点数 bool flag = false; // 用于截断无法正向松弛,避免无谓的操作 for (int j = 0; j < all; ++j) { // 对于每一条边进行|V|次松弛,因为是求正权回环 if (dis[exc[j].b] < (dis[exc[j].a] - exc[j].c) * exc[j].r) { dis[exc[j].b] = (dis[exc[j].a] - exc[j].c) * exc[j].r; flag = true; } } if (!flag) break; } //if (dis[s] > v) // 这样不行 // return true; for (int i = 0; i < all; ++i) //找到正环能无限松弛,找到正权回路 if (dis[exc[i].b] < (dis[exc[i].a] - exc[i].c) * exc[i].r) return true; return false; } int main() { //freopen("temp.txt", "r", stdin); int a, b; double rab, cab, rba, cba; // ratio, commission cin >> n >> m >> s >> v; for (int i = 0; i < m; ++i) { cin >> a >> b >> rab >> cab >> rba >> cba; exc[all].a = a; exc[all].b = b; exc[all].r = rab; exc[all++].c = cab; exc[all].a = b; exc[all].b = a; exc[all].r = rba; exc[all++].c = cba; } if (bellman_ford()) cout << "YES" << endl; else cout << "NO" << endl; return 0; }