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;
}