题目大意:
题目链接:http://poj.org/problem?id=2240
求一些货币互相兑换后能否增值。
思路:
负环半模板题。不能再这样水下去了
很明显的,把货币之间的利率转换成一个相乘的最短路问题,那么如果从一个点开始,走了一圈回到原来那个点时,钱数上涨了,那么久说明增值了。
这道题的输入是比较奇怪的,可以使用来把字符串转换成数字,然后跑正常的负环。
代码:
#include <cstdio>
#include <cstring>
#include <map>
#include <iostream>
#include <queue>
#include <string>
using namespace std;
const int N=35;
const int M=N*N;
const double Inf=1000000000000000000.0;
int n,m,head[N],tot,CNT,cnt[N];
double dis[N];
bool vis[N];
string s1,s2;
map<string,int> Name;
struct edge
{
int next,to;
double dis;
}e[M];
void add(int from,int to,double dis)
{
e[++tot].to=to;
e[tot].dis=dis;
e[tot].next=head[from];
head[from]=tot;
}
bool spfa()
{
for (int i=1;i<=n;i++)
dis[i]=0,vis[i]=0,cnt[i]=0;
queue<int> q;
q.push(1);
dis[1]=1.0;
vis[1]=1;
cnt[1]=1;
while (q.size())
{
int u=q.front(),v;
q.pop();
vis[u]=0;
for (int i=head[u];~i;i=e[i].next)
{
v=e[i].to;
if (dis[v]<dis[u]*e[i].dis)
{
dis[v]=dis[u]*e[i].dis;
cnt[v]=cnt[u]+1;
if (cnt[v]>n) return 1;
if (!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
return 0;
}
int main()
{
while (scanf("%d",&n)&&n)
{
memset(head,-1,sizeof(head));
memset(e,0,sizeof(e));
Name.clear();
tot=0;
for (int i=1;i<=n;i++)
{
//scanf("%s",&s1);
cin>>s1;
Name[s1]=i; //记录编号
}
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
double x;
//scanf("%s%d%s",&s1,&x,&s2);
cin>>s1>>x>>s2;
add(Name[s1],Name[s2],x); //取编号来连边
}
printf("Case %d: ",++CNT);
if (spfa()) printf("Yes
");
else printf("No
");
}
}