zoukankan      html  css  js  c++  java
  • Currency Exchange---poj1860 ( spfa, 回路,最长路)

    题目链接: http://poj.org/problem?id=1860

    题解:

    两种情况YES,一种是存在正权回路;
           一种是求最长路后,实现了增值,也是YES;
    用spfa来判断是否存在正权回路,其实spfa是可以用来判断是否存在回路的,不管是正权还是负权,只不过它们松弛的条件不同,正权的话,我们是往dis[]权值增大的方向松弛,负权的话,我们是往dis[]权值减少的方向松弛,然后判断是否存在回路只要看有没有一点入队列的次数大于n就行了用spfa来判断是否存在正权回路,其实spfa是可以用来判断是否存在回路的,不管是正权还是负权,只不过它们松弛的条件不同,正权的话,我们是往dis[]权值增大的
     
    如果存在一个环(从某个点出发又回到自己的路径),而且这个环上所有权值之和是负数,那这就是一个负权环,也叫负权回路;同理正权回路;
     
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <stdlib.h>
    #include <math.h>
    #include <queue>
    #include <algorithm>
    using namespace std;
    #define N 210
    #define INF 0xfffffff
    double dist[N], V;
    int cnt, Head[N], num[N], vis[N];
    int n, m, s;
    
    struct Edge
    {
        int v, next;
        double r, c;
    }e[N];
    
    void Add(int u, int v, double r, double c)
    {
        e[cnt].v = v;
        e[cnt].r = r;
        e[cnt].c = c;
        e[cnt].next = Head[u];
        Head[u] = cnt++;
    }
    
    bool spfa()///spfa模板;
    {
        memset(vis, 0, sizeof(vis));
        memset(num, 0, sizeof(num));
        queue<int>Q;
        vis[s] = 1;
        dist[s] = V;
        Q.push(s);
        num[s]++;
        while(Q.size())
        {
            int p=Q.front();
            Q.pop();
            vis[p] = 0;
            for(int i=Head[p]; i!=-1; i=e[i].next)
            {
                int q = e[i].v;
                if(dist[q] < (dist[p] - e[i].c) * e[i].r)///注意松弛的变化;
                {
                    dist[q] = (dist[p] - e[i].c) * e[i].r;
                    if(!vis[q])
                    {
                        vis[q] = 1;
                        Q.push(q);
                        num[q] ++;
                        if(num[q]>n)
                            return true;///存在正权回路;
                    }
                }
            }
    
        }
        if(dist[s]>V)///最长路后,实现了增值;
            return true;
        return false;
    }
    
    int main()
    {
        int a, b;
        double rab, rba, cab, cba;
        while(scanf("%d%d%d%lf", &n, &m, &s, &V)!=EOF)
        {
            cnt = 0;
            memset(Head, -1, sizeof(Head));
            memset(dist, 0, sizeof(dist));
            for(int i=1; i<=m; i++)
            {
                scanf("%d%d%lf%lf%lf%lf", &a, &b, &rab, &cab, &rba, &cba);
                Add(a, b, rab, cab);
                Add(b, a, rba, cba);
            }
            if( spfa() )
                printf("YES
    ");
            else
                printf("NO
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    第六周总结
    第五周总结
    第四周总结
    7-1 抓老鼠啊~亏了还是赚了?
    春季学期第八周作业
    春季学期第七周作业
    春季学期第六周作业
    春季学期第五周作业
    春季学期第四周作业
    春季学期第三周作业
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4798985.html
Copyright © 2011-2022 走看看