zoukankan      html  css  js  c++  java
  • hdu1217(spfa,存在环,但需要将环的元素历遍一次.....求乘积的最大)

    题意:有n个国家货币,给出m种两个国家之间的货币兑换率,求是否可以盈利.......

    思路:其实就是看国家货币兑换间是否存在一个环,使得从v点出发时,dis[v]=1,经过环回到v点时,dis[v]>1.......当然,路径是单向的。这个题目的松弛是:dis[i]<dis[v]*map[v][i],只单单spfa来说,要判断存在一个正环,那么就是某个点被历遍>=n+1次,从而判断这个环不存在“最大路”.....但是,就这题目而已,我们不需要判断最大路是否存在,我们只需要判断,是否可以盈利。可以盈利的话,那么从某个点p出发,经过一个环,回到点p,通过松弛,dis[p]>1,说明可以盈利,否则就是不能。那么可以使用数组进行标记,每次一个点可以松弛(就是满足dis[i]<dis[v]*map[v][i]),那么先更新这个点的最大值,然后判断这个点是否在队列里面,在的话,就不需要压入队列,否则压入队列......一个点出队列的时候,它相应的标记数要清零.......

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    struct node
    {
        int e;
        double d;
    };
    char t[50][100],s[1000][100],s1[1000][100],vist[1000];
    int n,m,flg;
    double dis[100],x[1000];
    vector<node>vet[1000];
    
    void spfa(int v)
    {
        for(int i=0;i<=n;i++)
        dis[i]=0;
        dis[v]=1.0;
        queue<int>q;
        q.push(v);
        vist[v]=1;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            vist[u]=0;
            for(int i=0;i<vet[u].size();i++)
            {
                node p=vet[u][i];
                //printf("%d %d %.3lf
    ",u,p.e,p.d);
    
                if(dis[p.e]<dis[u]*p.d)
                {
                    dis[p.e]=dis[u]*p.d;
                    //vist[p.e]=1;
                    if(vist[p.e]==0)
                    q.push(p.e);
                    vist[p.e]=1;
                    if(dis[v]>1.0)
                    {
                        flg=1;
                        return;
                    }
                }
            }
        }
    }
    int main()
    {
        int text=0;
        while(scanf("%d",&n)>0&&n)
        {
            for(int i=0;i<n;i++)
            scanf("%s",t[i]);
            for(int i=0;i<=n;i++)
            vet[i].clear();
    
            scanf("%d",&m);
            for(int i=0;i<m;i++)
            {
                scanf("%s %lf %s",s[i],&x[i],s1[i]);
                int xx,yy;
                for(int j=0;j<n;j++)
                {
                    if(strcmp(s[i],t[j])==0)
                    {
                        xx=j;
                    }
                    if(strcmp(s1[i],t[j])==0)
                    {
                        yy=j;
                    }
                }
                node p;
                p.e=yy;
                p.d=x[i];
                vet[xx].push_back(p);
                //p.e=xx;
                //vet[yy].push_back(p);
            }
            int i;
            printf("Case %d: ",++text);
            for(i=0;i<n;i++)
            {
                flg=0;
                memset(vist,0,sizeof(vist));
                spfa(i);
                if(flg==1)
                {
                    printf("Yes
    ");
                    break;
                }
            }
            if(i==n)
            printf("No
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    Boost智能指针使用总结
    C++细节理解
    Mysql导入导出
    Mysql Join语法以及性能优化
    数据库设计三大范式
    Mysql子查询
    js面向对象的实现(example 一)
    js对象常用2中构造方法
    RequireJS 加载 easyui
    Cordova 打包 Android release app 过程详解
  • 原文地址:https://www.cnblogs.com/ziyi--caolu/p/3446002.html
Copyright © 2011-2022 走看看