POJ-2240-Arbitrage-spfa-寻找正权环


2240
此题与 1860 一样,求能否通过货币兑换率差挣钱


不同之处在于 1860 给定了某种初始货币,如果要保证挣钱的话,需要保证存在正权环且
【环上的点能回到源点】,因为1860给每一对点都给了往返的边,所以必然存在回到源点的路。因而只需要找正权环


而本题,没给出起点,也就是不保证正权环上的点能到回起点、、、于是加了个dfs判联通....后来发现正因为没给起点,只需找到正权环,那么必然挣钱【泥可以假设环上某一点作为起点即可】

注意有坑点:  存在边为 TOM 1.1 TOM; 即自环 

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
double min(double a,double b)
{ 	return a>b?b:a;}
double max(double a,double b)
{ 	return a<b?b:a;}
int inf=2147483647;
double eps=0.000001;   
struct node
{
	int v;
	double d;
	node(){}
	node(int vv,double a1 )
	{v=vv;d=a1;}
};
vector <node> mp[35];
int n,m; 
double dis[35];
int vis[35]; 
int cun[35];
int bellman(int xxx)
{
	queue<int> q;int i;
	for (i=1;i<=n;i++)
	dis[i]=0;
	memset(vis,0,sizeof(vis));
	memset(cun,0,sizeof(cun));
	dis[xxx]=1;
		vis[xxx]=1;
	q.push(xxx);
	while(!q.empty())
	{
		int tp=q.front();
		q.pop();
		for (i=0;i<mp[tp].size();i++)
		{
			int x=mp[tp][i].v;
			double tmp=mp[tp][i].d*dis[tp];
			if (tmp>dis[x] )
			{
				dis[x]=tmp;
				if (!vis[x])
				{
					vis[x]=1;
					q.push(x);
				}
				 if (++cun[x]>n) 
				 { return -1;}
			}
		}
		vis[tp]=0;
	}
	 
	return dis[xxx]-1>0;
}
 
int main()
{ 
	int  i,j;  
	int cnt=1;
	map<string ,int> uu;
	while(scanf("%d",&n)!=EOF)
	{ 
		if (!n) break;  
		uu.clear();
		string ss,s2;
		double d;
		int num=0;
	for (i=1;i<=n;i++)
	{
		cin>>ss;
		mp[i].clear();
		uu[ss]=++num;
	}
	scanf("%d",&m);
	for (i=1;i<=m;i++)
	{
		cin>>ss>>d>>s2;
		int x=uu[ss];
		int y=uu[s2];
		mp[x].push_back(node(y,d)); 
	}   
	int flag=0;
	for (i=1;i<=n;i++)
	{ 
		int ret=bellman(i); 
		if (ret!=0  )
		{ 	flag=1;	break; }
		 
	}
	
	printf("Case %d: %s\n",cnt++,flag?"Yes":"No") ;
	}
	return 0;
}

你可能感兴趣的:(POJ-2240-Arbitrage-spfa-寻找正权环)