POJ2240 Arbitrage(最短路径:SPFA||Floyd)

题意:

还是套汇问题,换货币看能不能增加钱

要点:

还是求负权回路,这题没有规定从哪边出发,所以Floyd算法比较好,但我刚学了一下spfa算法,强行用了一下也可以。

SPFA算法详解:点击打开链接


SPFA算法:

15380850 Seasonal 2240 Accepted 280K 47MS C++ 1448B 2016-04-12 08:34:54
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<queue>
using namespace std;
int n, m;
char name[100][100];
double map[100][100],dis[100];

bool spfa(int x)
{
	queue<int > que;
	bool vis[100];
	int count[100];
	memset(vis, false, sizeof(vis));
	memset(dis, 0, sizeof(dis));
	memset(count, 0, sizeof(count));
	dis[x] = 100.0;
	vis[x] = true;
	que.push(x);
	count[x]++;
	while (!que.empty())
	{
		int temp = que.front(); que.pop();
		vis[temp] = false;
		for (int i = 0; i < n;i++)
			if (dis[temp] * map[temp][i] > dis[i])
			{
				dis[i] = map[temp][i] * dis[temp];//松弛操作,有的点已经在队列中就不用入队
				if (!vis[i])		//如果当前点不在队列中
				{
					que.push(i);
					count[i]++;
					vis[i] = true;
					if (count[i] >= n)//如果入队次数大于等于n即有负权回路
						return true;
				}
			}	
	}
	return false;
}

int main()
{
	int num = 1;
	int x, y,i,j;
	while (~scanf("%d", &n), n)
	{
		memset(map, 0, sizeof(map));
		for (i = 0; i < n; i++)
			scanf("%s", name[i]);
		scanf("%d", &m);
		char temp1[100], temp2[100];
		double rate;	
		while(m--)
		{
			scanf("%s %lf %s", temp1, &rate, temp2);
			for (j = 0; j < n;j++)
				if (strcmp(name[j], temp1) == 0)
				{
					x = j;
					break;
				}
			for (j = 0; j < n; j++)
				if (strcmp(name[j], temp2) == 0)
				{
					y = j;
					break;
				}
			map[x][y] = rate;
		}
		bool flag = true;
		printf("Case %d: ", num++);
		for (i = 0; i < n;i++)		//每个点都找是否存在负权回路
			if (spfa(i))
			{
				flag = false;
				break;
			}
		if (!flag)
			printf("Yes\n");
		else
			printf("No\n");

	}
	return 0;
}

Floyd算法:

15380929 Seasonal 2240 Accepted 264K 47MS C++ 1109B 2016-04-12 09:26:32
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<queue>
using namespace std;
int n, m;
char name[100][100];
double map[100][100];

void floyd()
{
	for (int k = 0; k < n; k++)
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				if (map[i][j] < map[i][k] * map[k][j])
					map[i][j] = map[i][k] * map[k][j];
}

int main()
{
	int num = 1;
	int x, y,i,j;
	while (~scanf("%d", &n), n)
	{
		memset(map, 0, sizeof(map));
		for (i = 0; i < n; i++)
			map[i][i] = 1;		//一开始到自己的设成1,如果经过Floyd算法后改变这说明有负权回路
		for (i = 0; i < n; i++)
			scanf("%s", name[i]);
		scanf("%d", &m);
		char temp1[100], temp2[100];
		double rate;	
		while(m--)
		{
			scanf("%s %lf %s", temp1, &rate, temp2);
			for (j = 0; j < n;j++)
				if (strcmp(name[j], temp1) == 0)
				{
					x = j;
					break;
				}
			for (j = 0; j < n; j++)
				if (strcmp(name[j], temp2) == 0)
				{
					y = j;
					break;
				}
			map[x][y] = rate;
		}
		bool flag = true;
		floyd();
		for (i = 0; i < n;i++)
			if (map[i][i]>1)
			{
				flag = false;
				break;
			}
		printf("Case %d: ", num++);
		if (!flag)
			printf("Yes\n");
		else
			printf("No\n");

	}
	return 0;
}



posted @ 2016-04-12 08:53  seasonal  阅读(87)  评论(0编辑  收藏  举报