POJ原址:POJ1860
都不想说什么了,傻逼真是天注定,错了多少个地方,WA了多少次...
本来都已经是作学习之用了,基本照着参考程序抄的,还能抄错n次,下附的代码里无数的注释能见证我的崩溃啊···
收获:
1.bellmen-ford算法算是弄懂了,当然还不知道自己会不会运用,待会虫洞的题目一定自己写写看看
2.要分清double与int,可是深深的不同的
参考链接:
poj1860_bellman ford_sallyvion_新浪博客
POJ1860-Currency Exchange - ζёСяêτ - 小優YoU - 博客频道 - CSDN.NET
第二个是bellman-ford 的解释有参考,感觉说的不错
第三个小优的仍是主要程序的参考啦~
这是我悲伤的无数WA,其中accepted的那个还是由于我在崩溃后无限怀疑所参考的程序,所以浪费oj资源检验了一下,当然事实证明还是我错了。
程序:
#include<iostream>
using namespace std;
int n,m,s; //n代表货币种类数,m代表兑换点数量,s代表最初持有货币的种类
double v; //v代表最初持有s的量,注意v是double
int edge;
double wei[101]; //!!!因为这个没有用double,WA!!!
class exchange_points
{
public:
int a; //货币a
int b; //货币b
double r; //rate
double c; //手续费
}exc[202]; //因为是有向图
bool bellman()
{
int i,j;
memset(wei,0,sizeof(wei));//注意是定义成无穷小,因为要找的是最大路径
wei[s]=v; //将s作为源点,赋值
bool flag; //用于在不可能继续松弛的时候尽早break,作为优化
for(i=0;i<n-1;i++) //对除源点外的所有点进行松弛操作,共n-1次
{
flag=false; //flag先初始化为false
for(j=0;j<edge;j++)//对所有变进行松弛
{
if(wei[exc[j].b]<(wei[exc[j].a]-exc[j].c)*exc[j].r)
//注意是wei[exc[j].b]而不是exc[j].b,exc[j].b只能代表货币种类,不能代表价值
{
wei[exc[j].b]=(wei[exc[j].a]-exc[j].c)*exc[j].r;
flag=true;
}
}
//又一个错误的根源,以下if语句是在是在上面j的循环之外的!!!
//因为要等all个边松弛玩都没有一次flag=false才会这样
if(flag==false)
break;
}
//终于找到了WA的根源,这以下的之前居然在上面那个i的循环里面,,,简直啊。。。
//松弛完毕之后开始找是否有能无限松弛的正环
for(j=0;j<edge;j++) //对所有边进行检查
{
if(wei[exc[j].b]<(wei[exc[j].a]-exc[j].c)*exc[j].r) //检验发现还是可以松弛的顶点
return true;
}
return false;//正常情况无正环就return false
}
int main()
{
int x,y; //a,b两种临时用于交换的货币
double rab,cab,rba,cba; //临时的r和c,注意都是双向的
int k;
while(cin>>n>>m>>s>>v)
{
edge=0;
for(k=0;k<m;k++) //注意是m
{
cin>>x>>y>>rab>>cab>>rba>>cba;
exc[edge].a=x;
exc[edge].b=y; //在这里与参考的弄得不同,表明这里的x,y只在main这里临时用,虽然会导致x、y和rab等有点混乱
exc[edge].r=rab;
exc[edge++].c=cab;
exc[edge].a=y;
exc[edge].b=x;
exc[edge].r=rba;
exc[edge++].c=cba;
}
//终极检验
if(bellman())
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}