poj1860

昨天写好的直接关掉浏览器了没发出去。。


貌似思路很简单?1A。。不过我一开始想的是搜索,有环这个不好判断,而且有可能会多次走环,所以搜索的“最优”性无法体现。把边权赋值为当前从a点到b点换钱之后的价格,用Bellman-Ford算法来找正环。本来bellman是用来找负环,初始化是边权无穷大,而在这里,求可以无限松弛的最大边权路径,故,把边权初始化为无穷小,以正环代表可以挣钱,负环代表赔钱。

#include<iostream>

using namespace std;

int n;
int m;
int s;
double v;

int all;
double dis[101];

struct exchange_points
{
    int a;      //货币a
    int b;      //货币b
    double ratio;
    double costs;
}exc[202];

bool bellman()
{
    memset(dis, 0sizeof(dis));      //这里与bellman的目的刚好相反。初始化为源点到各点距离无穷小
    dis[s] = v;                       //即bellman本用于找负环,求最小路径,本题是利用同样的思想找正环,求最大路径

    bool flag;
    for (int i = 1; i <= n - 1; i++)
    {
        flag = false;
        for (int j = 0; j<all; j++)
        if (dis[exc[j].b] < (dis[exc[j].a] - exc[j].costs) * exc[j].ratio)         //寻找最长路径
        {                                                                 //进行比较的是"某点到自身的权值"和"某点到另一点的权值"
            dis[exc[j].b] = (dis[exc[j].a] - exc[j].costs) * exc[j].ratio;
            flag = true;
        }
        if (!flag)
            break;
    }

    for (int k = 0; k<all; k++)
    if (dis[exc[k].b] < (dis[exc[k].a] - exc[k].costs) * exc[k].ratio)           //正环能够无限松弛
        return true;

    return false;
}

int main(void)
{
    int a, b;
    double rab, cab, rba, cba;

    while (cin >> n >> m >> s >> v)
    {
        all = 0;
        for (int i = 0; i < m; i++)
        {
            cin >> a >> b >> rab >> cab >> rba >> cba;
            exc[all].a = a;
            exc[all].b = b;
            exc[all].ratio = rab;
            exc[all++].costs = cab;
            exc[all].a = b;
            exc[all].b = a;
            exc[all].ratio = rba;
            exc[all++].costs = cba;
        }

        if (bellman())
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
    return 0;
}

你可能感兴趣的:(图论,ACM题解报告)