POJ-1860.CurrencyExchange(Spfa判断负环模版题)
本题思路:每完成一次交换之后交换余额多于原钱数则存在正环,输出YES即可。
参考代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <queue> 5 using namespace std; 6 7 const int maxn = 5e2; 8 struct node { 9 int to, next; 10 double r, c; 11 } G[maxn]; 12 int n, m, s, num; 13 int head[maxn]; 14 double v; 15 double dist[maxn]; 16 bool vis[maxn]; 17 18 void addedge(int u, int v, double r, double c) { 19 G[++num].to = v; 20 G[num].r = r; 21 G[num].c = c; 22 G[num].next = head[u]; 23 head[u] = num; 24 } 25 26 bool Spfa(int s, double v) { 27 queue <int> Q; 28 Q.push(s); 29 dist[s] = v; 30 while(!Q.empty()) { 31 int now = Q.front(); Q.pop(); 32 vis[now] = false; 33 for(int k = head[now]; k; k = G[k].next) { 34 int next = G[k].to; 35 if(dist[next] < (dist[now] - G[k].c) * G[k].r) { 36 dist[next] = (dist[now] - G[k].c) * G[k].r; 37 if(!vis[next]) { 38 Q.push(next); 39 vis[next] = true; 40 } 41 } 42 } 43 if(dist[s] > v) return true; 44 } 45 return false; 46 } 47 48 int main () { 49 scanf("%d %d %d %lf", &n, &m, &s, &v); 50 int a, b; 51 double r1, c1, r2, c2; 52 while(m --) { 53 scanf("%d %d %lf %lf %lf %lf", &a, &b, &r1, &c1, &r2, &c2); 54 addedge(a, b, r1, c1); 55 addedge(b, a, r2, c2); 56 } 57 if(Spfa(s, v)) printf("YES\n"); 58 else printf("NO\n"); 59 return 0; 60 }
之前还没有用过链式前向星这种建图方法,这里简述一下。其中edge[i].to表示第i条边的终点,edge[i].next表示与第i条边同起点的下一条边的存储位置,edge[i].w为边权值.另外还有一个数组head[],它是用来
表示以i为起点的第一条边存储的位置。实际上你会发现这里的第一条边存储的位置其实在以i为起点的所有边的最后输入的那个编号。head[]数组一般初始化为-1,对于加边的add函数是这样的。初始化一个变量num为0来记录当前总共的边的个数。
附一篇大佬的博客:博客链接
再附上我的邻接表建图的代码:这个较慢一点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstring> 3 #include <vector> 4 #include <queue> 5 using namespace std; 6 7 const int maxn = 100 + 5; 8 const double INF = 0x3f3f3f3f; 9 struct node { 10 int to; 11 double commission; 12 double rate; 13 }; 14 vector<node> G[maxn]; 15 double dist[maxn]; 16 bool vis[maxn]; 17 int n, m, s; 18 double v; 19 bool ans; 20 21 bool spfa() { 22 memset(vis, false, sizeof vis); 23 for(int i = 1; i <= n; i ++) 24 dist[i] = 0; 25 dist[s] = v; 26 queue <int> Q; 27 Q.push(s); 28 while(!Q.empty()) { 29 int now = Q.front(); Q.pop(); 30 for(int i = 0; i < G[now].size(); i ++) { 31 node next = G[now][i]; 32 if(dist[next.to] < (dist[now] - next.commission) * next.rate) { 33 dist[next.to] = (dist[now] - next.commission) * next.rate; 34 if(!vis[next.to]) Q.push(next.to); 35 } 36 } 37 if(dist[s] > v) return true; 38 } 39 return false; 40 } 41 42 void addedge(int u, int v, double c, double r) { 43 G[u].push_back({v, c, r}); 44 } 45 46 int main () { 47 ios::sync_with_stdio(false); 48 int s1, s2; 49 double r1, c1, r2, c2; 50 ans = false; 51 cin >> n >> m >> s >> v; 52 for(int i = 0; i < m; i ++) { 53 cin >> s1 >> s2 >> r1 >> c1 >> r2 >> c2; 54 addedge(s1, s2, c1, r1); 55 addedge(s2, s1, c2, r2); 56 } 57 ans = spfa(); 58 if(ans) cout << "YES" << endl; 59 else cout << "NO" << endl; 60 return 0; 61 }
时间并不会因为你的迷茫和迟疑而停留,就在你看这篇文章的同时,不知道有多少人在冥思苦想,在为算法废寝忘食,不知道有多少人在狂热地拍着代码,不知道又有多少提交一遍又一遍地刷新着OJ的status页面……
没有谁生来就是神牛,而千里之行,始于足下!