bellman-ford算法,此题可看做最短路径问题,原因是,可把到源点的距离看做负值(自己建立的一个抽象模型,但不表示出来,考虑的时候按这个负值模型考虑)。那么求解此题,就是看有没有至少一个负权环,如果有的话,因为根据此题可知,所以包含这个负权环的任一路径且在这个负权环之后的所有节点都会是无穷小,源点到源点的某一路径一定包含这个负权环,所以只要这个负权环走过一定次数,一定会导致源点到源点的距离小于初始值,其实就是题目要求的大于初始值。不需要考虑正权环抵消对结果的影响,因为如果有正权环,完全可以不走这个正权环。因为从源点返回源点,至少会经过一个环,但如果没有负权环,就不会使得到的新距离小于初始值。还有一个需要注意的地方,在代码的注释中
//bellman-ford算法 #include <iostream> using namespace std; const int maxn=101; double r[2*maxn],c[2*maxn],d[maxn]; int u[2*maxn],v[2*maxn]; int n,m,s; double vv; bool bellman() { int i,j; for(i=1;i<=n;i++) d[i]=i==s?vv:0;//d[i]的上界为-0,意思是说松弛的时候小于号的右边如果<0,那么这样的松弛是不符合题意的,因为你不可能去得到一个数量为负值的钱,刚开始没有想清楚这个问题,盲目的赋了个界,无数次wa; for(i=1;i<n;i++) { for(j=1;j<=2*m;j++) { if(d[v[j]]<((d[u[j]]-c[j])*r[j])) d[v[j]]=(d[u[j]]-c[j])*r[j]; } } for(j=1;j<=2*m;j++) { if(d[v[j]]<((d[u[j]]-c[j])*r[j])) return true; } return false; } int main() { while(cin>>n>>m>>s>>vv) { int i,j; int tu,tv; double tr1,tc1,tr2,tc2; for(i=1;i<=m;i++) { cin>>tu>>tv>>tr1>>tc1>>tr2>>tc2; u[i]=tu;v[i]=tv;r[i]=tr1;c[i]=tc1; u[i+m]=tv;v[i+m]=tu;r[i+m]=tr2;c[i+m]=tc2; } bool result=bellman(); if(result) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }