POJ 1860 Currency Exchange (BellmanFord算法逆用 判斷圖是否存在正環)

題目鏈接

POJ1860

題目大意

有N(1 N 100)種貨幣(標號1到N),M種貨幣的兩兩兌換法則(包括匯率r和手續費c),具體的法則是:當你用100A幣交換B幣時,A到B的匯率是29.75,手續費是0.39,那麼你可以得到(100 - 0.39) * 29.75 = 2963.3975 B幣。現在一個人手頭有S型號貨幣,量爲V,問他能否經過交換最終得到S型號貨幣且數額增加(交易過程中貨幣不能爲負)。

分析

一種貨幣看成圖上的一個結點,一種兌換方式可以看成一條邊
A到B的權值爲(Va-Cab)*Rab,注意S到S的權值爲V。
構圖完畢後可以發現題目就是要判斷圖是否構成正權迴路,所以可以逆用Bellman-Ford算法求最長路,用相反的鬆弛條件鬆弛N-1輪,如果還能繼續鬆弛則存在正權迴路。

代碼

#include <iostream>
#include <cstdio>
using namespace std;

const int MAXM=210;
const int MAXN=110;

struct Edge
{
    int beg;
    int end;
    double r,c;
};
Edge edge[MAXM];

int edgenum,n,m,s;
double dis[MAXN],val;
void Add_Edge(int beg,int end,double r,double c)
{
    edgenum++;
    edge[edgenum].beg=beg;//起點貨幣
    edge[edgenum].end=end;//終點貨幣
    edge[edgenum].r=r;//匯率
    edge[edgenum].c=c;//手續費
}
bool Bellmen_Ford()
{
    for (int i=1;i<=n;i++) dis[i]=0;//這裏與bellman的目的剛好相反。初始化爲源點到各點距離無窮小
    dis[s]=val;//初始手裏的貨幣量
    for (int k=1;k<=n-1;k++)//進行N-1輪鬆弛
    {
        bool flag=false;
        for (int i=1;i<=edgenum;i++)
        {
            int u=edge[i].beg;
            int v=edge[i].end;
            if (dis[v]<(dis[u]-edge[i].c)*edge[i].r)//尋找最長路徑
            {                                       ////進行比較的是"某點到自身的權值"和"某點到另一點的權
                flag=true;
                dis[v]=(dis[u]-edge[i].c)*edge[i].r;
            }
        }
        if (!flag) return false;
    }
    for (int i=1;i<=edgenum;i++)//正環能夠無限鬆弛
        if (dis[edge[i].end]<(dis[edge[i].beg]-edge[i].c)*edge[i].r)
            return true;
    return false;
}
int main()
{
    int a,b;
    double R_ab,C_ab,R_ba,C_ba;
    while (scanf("%d%d%d%lf",&n,&m,&s,&val)!=EOF)
    {
        edgenum=0;
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d%lf%lf%lf%lf",&a,&b,&R_ab,&C_ab,&R_ba,&C_ba);
            Add_Edge(a,b,R_ab,C_ab);
            Add_Edge(b,a,R_ba,C_ba);
        }
        bool ans=Bellmen_Ford();
        if (ans) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章