POJ 2240

之前在POJ做过另外一道类似货币判断负环的问题,感觉那个更有挑战性也更富有变化些

这道题因为是有多组输入,为了避免一直初始化清空之前运算时用过的变量,同时也为了利用SPFA方式(从代码实现的间接性和容易成程度,应该原始的BellmanFord而非优化后的SPFA算法更合适)尝试利用类进行管理

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <string>
#include <stack>
#include <map>
#include <set>
using namespace std;

const int maxn= 35;

struct Edge
{
	int f, t;
	double v;	
};
class SPFA
{
	int n, m;
	vector<Edge> G[maxn];
	map<string, int> hash;
	int inq[maxn], cnt[maxn];
	double d[maxn];
public:
	SPFA()= default;
	int solve(const int nn)
	{
		string n_c, n_ct;
		double v;
		n= nn;
		for (int i= 0; i< n; ++i){
			cin>>n_c;
			hash.insert(pair<string, int>(n_c, i));
		}
		scanf("%d", &m);
		for (int i= 0; i< m; ++i){
			cin>>n_c;
			scanf("%lf", &v);
			cin>>n_ct;
			G[hash[n_c]].push_back((Edge){hash[n_c], hash[n_ct], v});
		}

		for (int i= 0; i< n; ++i){
			if (!Judge(i)){
				return 1;
			}
		}

		return 0;
	}
	int Judge(int s)
	{
		queue<int> Q;
		memset(d, 0, sizeof(d));
		memset(inq, 0, sizeof(inq));
		memset(cnt, 0, sizeof(cnt));
		d[s]= 1;
		Q.push(s);
		inq[s]= 1;

		while (!Q.empty()){
			int f= Q.front();
			Q.pop();
			inq[f]= 0;

			for (vector<Edge>::iterator gIter= G[f].begin(); G[f].end()!= gIter; ++gIter){
				double v= gIter->v; 
				int t= gIter->t;
				if (v*d[f] > d[t]){
					d[t]= v*d[f];
					if (!inq[t]){
						Q.push(t);
						inq[t]= 1;
						if (++cnt[t]> n){
							return 0;
						}
					}
				}
			}
		}

		return 1;
	}
	~SPFA()= default;
	
};

int main(int argc, char const *argv[])
{
	int n;
	int kase= 0;
	while (~scanf("%d", &n) && n){
		SPFA poj2240;
		if (poj2240.solve(n)){
			printf("Case %d: Yes\n", ++kase);
		}
		else{
			printf("Case %d: No\n", ++kase);
		}
	}	

	return 0;
}
posted @ 2021-04-09 20:40  IdiotNe  阅读(46)  评论(0编辑  收藏  举报