zoukankan      html  css  js  c++  java
  • poj_1860 SPFA

    题目大意

        有N种货币,M个兑换点,每个兑换点只能相互兑换两种货币。设兑换点A可以兑换货币C1和C2,给出rate(C1--C2)表示1单位的C1货币可以兑换出的C2货币数目,rate(C2--C1)表示1单位的C2货币可以兑换出的C1货币数目,commision(C1)表示用C1兑换C2的时候兑换点需要收取的佣金,commison(C2)表示C2到C1兑换时候兑换点收取的佣金,那么进行C1-C2的兑换操作实际得到的结果为 (amount(C1)-commision(C1))*rate(C1-C2),同理C2-C1的兑换操作最终得到的C1为 (amount(C2)-commision(C2))*rate(C2-C1)。 
        先给定数目为V的货币S,问是否有一种兑换方法,使得经过兑换之后,S的数目增加。

    题目分析

        要求从货币S经过若干次兑换,最终回到S,使得S的数目增加。将N种货币视为N个点,将M个兑换点视为M条双向路径,则题目转换为是否存在一条回路使得从点S出发回到S,初始值增加。 
        可以求出从S到每种货币经过路径兑换之后所能得到的最大数值,类似求单源最短路径,题目的结果就是从S到S的最大数值是否大于初始值V。 
        采用SPFA算法求解。由于图中的任意一条边都是双向的,且其中的回路可以走任意多次(回路上的货币可能一直增加),则如果存在使得soruce货币增加的回路,回路上的点会被push进队列,则一定能够回到source节点;如果不存在使得source货币增加的路径,则肯定不存在一直循环增加的回路,那么队列肯定不会一直增长不会陷入死循环;判断source到source的环是否使得钱增加即可,若增加则直接返回true

    实现(c++)

    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    
    struct Edge{
    	int vertex;
    	double commision;
    	double rate;
    };
    vector<vector<Edge> > gEdges;
    
    double gCurrency[105];	//将每种货币视为图上的一个节点,gCurrency用于存放每个节点的钱数
    
    bool Spfa(int source, int n, double init_value){
    	queue<int> Q;
    	Q.push(source);
    	for (int i = 0; i <= n; i++){
    		gCurrency[i] = 0;
    	}
    	gCurrency[source] = init_value;		//SPFA算法
    	while (!Q.empty()){
    		int v = Q.front();
    		Q.pop();
    		
    		for (int i = 0; i < gEdges[v].size(); i++){
    			Edge& e = gEdges[v][i];
    
    			double tmp = (gCurrency[v] - e.commision)*e.rate;
    			if (gCurrency[e.vertex] < tmp){
    				gCurrency[e.vertex] = tmp;
    				
    				Q.push(e.vertex);
    				
    
    				//由于图中的任意一条边都是双向的,且其中的回路可以走任意多次(回路上的货币可能一直增加),
    				//则如果存在使得soruce货币增加的回路,回路上的点会被push进队列,则一定能够回到source节点。
    
    				//如果不存在使得source货币增加的路径,则肯定不存在一直循环增加的回路,那么队列肯定不会一直增长
    				//不会陷入死循环
    
    				//判断source到source的环是否使得钱增加即可,若增加则直接返回true
    				if (e.vertex == source && gCurrency[source] > init_value){
    					return true;
    				}
    			}
    		}
    	}
    	return false;
    }
    
    int main(){
    	int n, m, s;
    	double v;
    	scanf("%d %d %d %lf", &n, &m, &s, &v);
    	int currency1, currency2;
    	double commision1, commision2, rate1, rate2;
    	gEdges.resize(105);
    	Edge e;
    	//初始化图结构
    	for (int i = 0; i < m; i++){
    		scanf("%d %d %lf %lf %lf %lf", &currency1, &currency2, &rate1, &commision1, &rate2, &commision2);
    		e.vertex = currency2;
    		e.commision = commision1;
    		e.rate = rate1;
    		gEdges[currency1].push_back(e);
    
    		e.vertex = currency1;
    		e.commision = commision2;
    		e.rate = rate2;
    		gEdges[currency2].push_back(e);
    	}
    	if (Spfa(s, n, v)) //用SPFA判断,从source到source的路径中有没有使得钱数增加的
    		printf("YES
    ");
    	else
    		printf("NO
    ");
    	return 0;
    }
    
  • 相关阅读:
    IOS 模块并且发布到NPM
    处理npm publish报错问题
    IOS 应用发布流程
    《温故而知新》JAVA基础八
    Beta冲刺 (5/7)
    Beta冲刺 (4/7)
    Beta冲刺 (3/7)
    Beta冲刺 (2/7)
    软件测试(团队)
    福大软工 · BETA 版冲刺前准备(团队)
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4866069.html
Copyright © 2011-2022 走看看