POJ 2240 - SPFA - 正权环(最大路)

1.Question:

输入n代表有n个国家
之后的n行代表n个国家的名称
输入m代表有向边的个数
之后的代表我们国家货币之间的汇率

现在求,是否存在一条回路是的我们的交换货币之后原本的货币量增多

2.Solution:

本题是标准的判断回路的问题,我们需要将最短路的标准思路转变一下,首先,本题我们需要找到的是正权回路不是负权回路,我们只需要改变一下松弛策略就好,我们只要将松弛策略改成放大策略就ok,判断点进入队列的次数书否超过点数(这里有个问题,等于可以吗)
当然我们的Floyed算法也是可以的,我们的Floyed算法只需要判断我们的是否出现最后是否货币量比1大就好了

3.Code:

/*
Problem: 2240		User: lantianheyeqi
Memory: 376K		Time: 47MS
Language: C++		Result: Accepted
*/
#include"iostream"
#include"cstring"
#include"cstdio"
#include"cstdlib"
#define N 35

using namespace std;

double dis[N];
double map[N][N];
int n,m;
char nation[35][500];

int find(char data[])
{
	for(int i=1;i<=n;i++)
	{
		if(strcmp(nation[i],data)==0) return i;
	}
}

bool SPFA()
{
	memset(dis,0,sizeof(dis));
	int queue[N*N*N];
	int head=1;
	int tail=2;
	int num[N];
	memset(num,0,sizeof(num));
	bool book[N];
	memset(book,0,sizeof(book));
	queue[1]=1;
	book[1]=1;
	dis[1]=1;
	num[1]=1;
	while(head!=tail)
	{
		for(int i=1;i<=n;i++)
		{
			if(dis[i] < dis[queue[head]]*map[queue[head]][i])
			{
				dis[i] = dis[queue[head]]*map[queue[head]][i];
				if(book[i] == 0)
				{
					book[i]=1;
					queue[tail++]=i;
					num[i]++;
					if(num[i] > n) return true;
				}
			}
		}
		book[queue[head]]=0;
		head++;
	}
	return false;
}

int main()
{
	int t=1;
	while(scanf("%d",&n)&&n!=0)
	{
		memset(map,0,sizeof(map));
		for(int i=1;i<=n;i++) scanf("%s",nation[i]);
		scanf("%d",&m);
		double edge;
		char n1[500];
		char n2[500];
		int flag=0;
		for(int i=1;i<=m;i++) 
		{
			scanf("%s %lf %s",n1,&edge,n2);
			int index1 = find(n1);
    		int index2 = find(n2);
	    	map[index1][index2] = edge ;
	    	if(index1 == index2 && edge > 1) 
	    	{
	    		printf("Case %d: Yes\n",t++);
	    		flag=1;
	    		break;
	    	}
		}
		if(flag == 1) continue;
		bool judge = SPFA();
		if(judge) printf("Case %d: Yes\n",t++);
		else printf("Case %d: No\n",t++);
	}
	return 0;
}


你可能感兴趣的:(ACMer's,collection,图,POJ,专项题解)