/* *题目大意: * 有n种货币,而且每两种之间有汇率,如果a->b,b->c,c->a,然后他们之间的 * 所有汇率乘积大于1,那么就是一种获得利润的手段,题目要求输出yes. *解题思路: * 其实画图就知道,题目要的就是找到存在一个圈,并且这个圈所有权值的乘积 * 是正的,如果把最长路的关系条件由加法改为乘法,那么就是说找一个所有乘 * 积为的环。dij,floyd可以办到吗?显然不行,他们都处理不了带环的。这个时候 * spfa跟Bellman_ford就可以发挥无可比拟的优势了,不过囧了,这道题居然spfa * 比优化了的Bellman_ford慢了那么多,Bellman_ford 47ms,spfa要219ms *解题感想: * 记住想想咯,spfa的话,一个点入队n次,就马上判断有不可收敛的环了,入队n * 次,代表了人家松弛了n-1次。 */
Bellman_ford:
View Code
#include <iostream> #include <queue> #include <map> #include <string> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 35; const int MAXE = 100005; const double inf = 0x3f3f3f3f; typedef struct _node { int u, v; double w; int next; }N; map<string, int> index; N edge[MAXE]; int head[MAXN], cntEdge; void init(int n) { index.clear(); cntEdge = 0; for(int i = 0; i <= n; i++) { head[i] = -1; } } void addEdge(int u, int v, double w) { edge[cntEdge].u = u; edge[cntEdge].v = v; edge[cntEdge].w = w; edge[cntEdge].next = head[u]; head[u] = cntEdge++; } bool Bellman_ford(int s, int n) { double dis[MAXN]; for(int i = 0; i < n; i++) { dis[i] = -inf; } dis[s] = 1; for(int i = 0; i < n-1; i++) { bool flag = false; for(int j = 0; j < cntEdge; j++) { int u = edge[j].u, v = edge[j].v; double w = edge[j].w; if(dis[v] < dis[u] * w) { dis[v] = dis[u] * w; flag = true; } } if(!flag) break; } for(int f = 0; f < cntEdge; f++) { int u = edge[f].u, v = edge[f].v; double w = edge[f].w; if(dis[v] < dis[u] * w) return true;//有可以增值的环 } return false; } int main(void) { #ifndef ONLINE_JUDGE //freopen("in.txt", "r", stdin); #endif int n, m, cas_c = 1; while(scanf("%d", &n), n) { init(n); int cnt = 0; char name[1024], name1[1024]; for(int i = 0; i < n; i++) { scanf("%s", name); if(!index.count(name)) index[name] = cnt++; } scanf("%d", &m); double w; for(int i = 0; i < m; i++) { scanf("%s %lf %s", &name, &w, &name1); addEdge(index[name], index[name1], w); } //正图 bool sol = Bellman_ford(0, n); if(sol) printf("Case %d: Yes\n", cas_c++); else printf("Case %d: No\n", cas_c++); } return 0; }
spfa:
View Code
#include <iostream> #include <queue> #include <map> #include <queue> #include <string> #include <cstdio> #include <cmath> #include <cstring> using namespace std; const int MAXN = 35; const int MAXE = 100005; const double inf = 0x3f3f3f3f; typedef struct _node { int u, v; double w; int next; }N; map<string, int> index; N edge[MAXE]; int head[MAXN], cntEdge; void init(int n) { index.clear(); cntEdge = 0; for(int i = 0; i <= n; i++) { head[i] = -1; } } void addEdge(int u, int v, double w) { edge[cntEdge].u = u; edge[cntEdge].v = v; edge[cntEdge].w = w; edge[cntEdge].next = head[u]; head[u] = cntEdge++; } bool spfa(int s, int n) { int inQ[MAXN] = {0}, in[MAXN] = {0}; double dis[MAXN]; for(int i = 0; i < n; i++) dis[i] = -inf; dis[s] = 1; queue<int> Q; Q.push(s); inQ[s] = 1; in[s]++; while(!Q.empty()) { int pre = Q.front(); Q.pop(); inQ[pre] = 0; for(int f = head[pre]; f != -1; f = edge[f].next) { int v = edge[f].v; double w = edge[f].w; if(dis[v] < dis[pre] * w) { dis[v] = dis[pre] * w; if(!inQ[v]) { inQ[v] = 1; Q.push(v); in[v]++; if(in[v] > n) return true; } } } } return false; } int main(void) { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int n, m, cas_c = 1; while(scanf("%d", &n), n) { init(n); int cnt = 0; char name[1024], name1[1024]; for(int i = 0; i < n; i++) { scanf("%s", name); if(!index.count(name)) index[name] = cnt++; } scanf("%d", &m); double w; for(int i = 0; i < m; i++) { scanf("%s %lf %s", &name, &w, &name1); addEdge(index[name], index[name1], w); } //正图 bool sol = spfa(0, n); if(sol) printf("Case %d: Yes\n", cas_c++); else printf("Case %d: No\n", cas_c++); } return 0; }