zoukankan      html  css  js  c++  java
  • POJ2240 Arbitrage 货币汇率

    我用了Bellman_ford判断正权圈,还可以用floyd,够酷。

    /*
    *题目大意:
    *        有n种货币,而且每两种之间有汇率,如果a->b,b->c,c->a,然后他们之间的
    *        所有汇率乘积大于1,那么就是一种获得利润的手段,题目要求输出yes.
    *解题思路:
    *        其实画图就知道,题目要的就是找到存在一个圈,并且这个圈所有权值的乘积
    *        是正的,如果把最长路的关系条件由加法改为乘法,那么就是说找一个所有乘
    *        积为的环。dij,floyd可以办到吗?显然不行,他们都处理不了带环的。这个时候
    *        spfa跟Bellman_ford就可以发挥无可比拟的优势了,不过囧了,这道题居然spfa
    *        比优化了的Bellman_ford慢了那么多,Bellman_ford 47ms,spfa要219ms
    *解题感想:
    *        记住想想咯,spfa的话,一个点入队n次,就马上判断有不可收敛的环了,入队n
    *        次,代表了人家松弛了n-1次。
    */
    View Code
    #include <iostream>
    #include <queue>
    #include <map>
    #include <string>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int MAXN = 35;
    const int MAXE = 100005;
    const double inf = 0x3f3f3f3f;
    
    typedef struct _node
    {
        int u, v;
        double w;
        int next;
    }N;
    map<string, int> index;
    N edge[MAXE];
    int head[MAXN], cntEdge;
    
    void init(int n)
    {
        index.clear();
        cntEdge = 0;
        for(int i = 0; i <= n; i++)
        {
            head[i] = -1;
        }
    }
    
    void addEdge(int u, int v, double w)
    {
        edge[cntEdge].u = u;
        edge[cntEdge].v = v;
        edge[cntEdge].w = w;
        edge[cntEdge].next = head[u];
        head[u] = cntEdge++;
    }
    
    bool Bellman_ford(int s, int n)
    {
        double dis[MAXN];
        for(int i = 0; i < n; i++)
        {
            dis[i] = -inf;
        }
        dis[s] = 1;
    
        for(int i = 0; i < n-1; i++)
        {
            bool flag = false;
            for(int j = 0; j < cntEdge; j++)
            {
                int u = edge[j].u, v = edge[j].v;
                double w = edge[j].w;
                if(dis[v] < dis[u] * w)
                {
                    dis[v] = dis[u] * w;
                    flag = true;
                }
            }
            if(!flag)
                break;
        }
    
        for(int f = 0; f < cntEdge; f++)
        {
            int u = edge[f].u, v = edge[f].v;
            double w = edge[f].w;
            if(dis[v] < dis[u] * w)
                return true;//有可以增值的环
        }
        return false;
    }
    
    int main(void)
    {
    #ifndef ONLINE_JUDGE
        //freopen("in.txt", "r", stdin);
    #endif
    
        int n, m, cas_c = 1;
        while(scanf("%d", &n), n)
        {
            init(n);
            int cnt = 0;
            char name[1024], name1[1024];
            for(int i = 0; i < n; i++)
            {    
                scanf("%s", name);
                if(!index.count(name))
                    index[name] = cnt++;
            }
            
            scanf("%d", &m);
            double w;
            for(int i = 0; i < m; i++)
            {
                scanf("%s %lf %s", &name, &w, &name1);
                addEdge(index[name], index[name1], w);
            }
    
            //正图
            bool sol = Bellman_ford(0, n);
            if(sol)
                printf("Case %d: Yes\n", cas_c++);
            else
                printf("Case %d: No\n", cas_c++);
        }
        return 0;
    }

    再用了spfa写了一遍,结果发现spfa怎么时间慢了,数据问题吗?还是O(k*e)里面的k不稳定?

    spfa:

    View Code
    #include <iostream>
    #include <queue>
    #include <map>
    #include <queue>
    #include <string>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int MAXN = 35;
    const int MAXE = 100005;
    const double inf = 0x3f3f3f3f;
    
    typedef struct _node
    {
        int u, v;
        double w;
        int next;
    }N;
    map<string, int> index;
    N edge[MAXE];
    int head[MAXN], cntEdge;
    
    void init(int n)
    {
        index.clear();
        cntEdge = 0;
        for(int i = 0; i <= n; i++)
        {
            head[i] = -1;
        }
    }
    
    void addEdge(int u, int v, double w)
    {
        edge[cntEdge].u = u;
        edge[cntEdge].v = v;
        edge[cntEdge].w = w;
        edge[cntEdge].next = head[u];
        head[u] = cntEdge++;
    }
    
    bool spfa(int s, int n)
    {
        int inQ[MAXN] = {0}, in[MAXN] = {0};
        double dis[MAXN];
        for(int i = 0; i < n; i++)
            dis[i] = -inf;
        
        dis[s] = 1;
        queue<int> Q;
        Q.push(s);
        inQ[s] = 1;
        in[s]++;
    
        while(!Q.empty())
        {
            int pre = Q.front();
            Q.pop();
            inQ[pre] = 0;
    
            for(int f = head[pre]; f != -1; f = edge[f].next)
            {
                int v = edge[f].v;
                double w = edge[f].w;
                if(dis[v] < dis[pre] * w)
                {
                    dis[v] = dis[pre] * w;
                    if(!inQ[v])
                    {
                        inQ[v] = 1;
                        Q.push(v);
                        in[v]++;
                        if(in[v] > n)
                            return true;
                    }
                }
            }
        }
        return false;
    }
    
    int main(void)
    {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
    #endif
    
        int n, m, cas_c = 1;
        while(scanf("%d", &n), n)
        {
            init(n);
            int cnt = 0;
            char name[1024], name1[1024];
            for(int i = 0; i < n; i++)
            {    
                scanf("%s", name);
                if(!index.count(name))
                    index[name] = cnt++;
            }
            
            scanf("%d", &m);
            double w;
            for(int i = 0; i < m; i++)
            {
                scanf("%s %lf %s", &name, &w, &name1);
                addEdge(index[name], index[name1], w);
            }
    
            //正图
            bool sol = spfa(0, n);
            if(sol)
                printf("Case %d: Yes\n", cas_c++);
            else
                printf("Case %d: No\n", cas_c++);
        }
        return 0;
    }
  • 相关阅读:
    how to uninstall devkit
    asp.net中bin目录下的 dll.refresh文件
    查找2个分支的共同父节点
    Three ways to do WCF instance management
    WCF Concurrency (Single, Multiple, and Reentrant) and Throttling
    检查string是否为double
    How to hide TabPage from TabControl
    获取当前系统中的时区
    git svn cygwin_exception
    lodoop打印控制具体解释
  • 原文地址:https://www.cnblogs.com/cchun/p/2645064.html
Copyright © 2011-2022 走看看