poj1860解题报告(两种解法)

给定一些站点可以交换货币,判断持有某一种货币的人是否可以增值财产.

解法1:基本思路是寻找一个正环,包含出发点s.没有用Bellman_ford算法,采用的是深度搜索优先(DFS),当一个节点被访问过之后,再次访问,就说明找到了一条回路.这时候需要判断找到的回路是不是正的.比较当前节点的货币数量与出发时节点的货币数量(一个节点可能有很多货币状态,因为可以通过不同的途径到达该节点,所以需要利用一个栈把状态保存起来),当前状态和前一个入栈的状态就是应该比较的对象.如果满足就退出函数.

//解法1为了验证答案,从txt文档里面读入了大量数据作测试,没有按照poj上的手动输入.

#include "iostream"
#include "fstream"
#include "sstream"
#include "string"
#include "vector"
using namespace std;
struct record
{
    int next;
    double rate;
    double com;
};
struct List
{
    int index;
    vector<record> ptr;
};

typedef  vector<List> G;
int N, M, S;
double V;
bool isvisited[101] = { false };
int a, b;
double r1, c1, r2, c2;
static bool isyes = false;
inline double convert(double money, double rate, double commision)
{
    return ((money - commision)*rate) ;//返还转换的钱
}
void func(int sort, double money, const vector<List> &graph,
    vector<vector<double>>& Money,vector<int>& indegree)
{
    //sort代表当前所在的节点
    const vector<record> &temp = graph[sort].ptr;
    if (indegree[sort] < 0||money<=0)
        return;
    else if (isvisited[sort])//说明该节点被访问过,找到一个环
    {
        vector<double>::iterator p = (Money[sort].end() - 2);
        if (money>*p)//一个正环
        {
            isyes = true;
            cout << sort << endl;
        }
        return;
    }
    isvisited[sort] = true;
    for (int it = 0; it != temp.size()&&isyes!=true; ++it)//
    {
        int index = (temp[it]).next;
        double rate = (temp[it]).rate, com = (temp[it]).com;
        -- indegree[index];
        Money[index].push_back(convert(money, rate, com));
        func(index, Money[index].back(),graph,Money,indegree);
        Money[index].pop_back();
        ++indegree[index];
    }
    isvisited[sort] = false;
}

int main()
{
    string line;
    ifstream is("Text.txt");
    getline(is, line);
    istringstream R1(line);
    R1 >> N >> M >> S >> V;
    G graph(N + 1);
    vector<int> indegree(N + 1);
    vector<vector<double>> Money(N + 1);
    int x = M;
    while (x--)
    {
        if (is)
        {
            is.clear();
            getline(is,line);
            istringstream R(line);
            while (R >> a >> b >> r1 >> c1 >> r2 >> c2)
            {
                record temp1 = { b, r1, c1 };
            graph[a].ptr.push_back(temp1);//存入一个相邻节点
            record temp2 = { a, r2, c2 };
            graph[b].ptr.push_back(temp2);
            ++indegree[a], ++indegree[b];//入度加一
            }           
        }
    }
    //寻找一个环,起点为S
    Money[S].push_back (V);
    func(S,V,graph,Money,indegree);

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

解法二:采用网上普遍的Bellman_ford算法,寻找一个环,并且按照货币兑换的方式来进行松弛.基本就是算法导论上的思路。

#include "iostream"
#include "fstream"
#include "sstream"
#include "string"
#include "vector"
using namespace std;
int N, M, S,a,b;
double r1,c1,r2,c2,V;
const double Inf = 1000000000;
struct Edge
{
    int beg;
    int end;
    double r, c;
};
typedef vector<Edge> E;
typedef vector<double> Dis;
bool relax(Edge& one_edge,Dis &D)
{
    double result = (D[one_edge.beg] - one_edge.c)*one_edge.r;
    if (result > D[one_edge.end])
    {
        D[one_edge.end] = result;
        return true;
    }
    else
        return false;
}
bool bellman_ford(E edge,Dis &D)
{
    //初始化已经在外部完成
    for (size_t i = 1; i != N; ++i)//遍历|V|-1个点
    {
        bool flag = false;
        for (auto &it : edge)
        {
            if (relax(it,D)) flag = true;//本次松弛成功了至少一次
        }
        if (D[S] > V) return true;
        if (!flag)  return false;//本次遍历没有进行松弛,且没有找到正环
    }
    //检测是否找到正环
    for (auto &it : edge)
        if (relax(it,D)) return true;//如果还能松弛,说明存在正环

    return false;
}
int main()
{
    cin >> N >> M >> S >> V;
    E edge(M + 1);
    vector<double> D (N+1);
    D[S] = V;
    while (M--)
    {
        cin >> a >> b >> r1 >> c1 >> r2 >> c2;
        Edge temp = { a, b, r1, c1 }, temp2 = { b, a, r2, c2 };
        edge.push_back(temp), edge.push_back(temp2);
    }
    bool ans = bellman_ford(edge, D);
    if (ans)
        cout << "YES" << endl;
    else
        cout << "NO" << endl;
    return 0;
}

你可能感兴趣的:(算法,poj)