// poj-1860: bellmanFord 求正权回路
题目大意:有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加
解题思路:如果能增加的话,则图中存在正权回路。用bellmanFord,改变松弛条件,改求最长路。每次value值能增大的话更新,如果能在N-1内更新出最长路,则不存在正权回路,输出"NO";如果在第N次能继续松弛,则存在,输出"YES"
AC Code : bellmanFord Memory: 172K Time: 0s
#include <iostream>
#include <cstdio>
#include <cstring>
#define MaxE 210
#define MaxV 105
using namespace std;
int N,M,S;
double V;
struct Edge
{
int to,next;
double rate,com;
}edge[MaxE];
int size,head[MaxV];
void InsertEdge(int v1,int v2,double rate1,double rate2,double com1,
double com2)
{ edge[size].to=v2,edge[size].rate=rate1,edge[size].com=com1;
edge[size].next=head[v1]; head[v1]=size++;
edge[size].to=v1,edge[size].rate=rate2,edge[size].com=com2;
edge[size].next=head[v2]; head[v2]=size++;
}
double value[MaxV]; //到 第i个点的最大value值
bool bellmanFord(int s)
{ int i,j,k;
int to;
bool flag;
memset(value,0,sizeof(value));
value[s]=V;
for(i=1;i<=N-1;i++)
{ flag=false;
for(j=1;j<=N;j++)
for(k=head[j];k+1;k=edge[k].next)
{ to=edge[k].to;
if(value[to]<(value[j]-edge[k].com)*edge[k].rate)
{ flag=true;
value[to]=(value[j]-edge[k].com)*edge[k].rate;
}
}
if(!flag)
break;
}
for(j=1;j<=N;j++)
for(k=head[j];k+1;k=edge[k].next)
{ to=edge[k].to;
if(value[to]<(value[j]-edge[k].com)*edge[k].rate)
return false;
}
return true;
}
void init()
{ int v1,v2,i;
double rate1,rate2,com1,com2;
size=0;memset(head,-1,sizeof(head));
scanf("%d%d%d%lf",&N,&M,&S,&V);
for(i=0;i<M;i++)
{ scanf("%d%d%lf%lf%lf%lf",&v1,&v2,&rate1,&com1,&rate2,&com2);
InsertEdge(v1,v2,rate1,rate2,com1,com2);
}
}
int main()
{
//freopen("in.txt","r",stdin);
init();
if(bellmanFord(S)) printf("NO");
else printf("YES");
return 0;
}