poj 3259 Wormholes spfa : 双端队列优化 判负环 O(k*E)

 1 /**
 2 problem: http://poj.org/problem?id=3259
 3 spfa判负环:
 4 当有个点被松弛了n次,则这个点必定为负环中的一个点(n为点的个数)
 5 spfa双端队列优化:
 6 维护队列使其dist小的点优先处理
 7 **/
 8 #include<stdio.h>
 9 #include<deque>
10 #include<algorithm>
11 using namespace std;
12
13 class Graphics{
14 const static int MAXN = 505;
15 const static int MAXM = 2505 * 2 + 205;
16 const static int INF = 0x7fffffff;
17 private:
18     struct Edge{
19         int to, dist, next;
20     }edge[MAXM];
21     int first[MAXN], sign, sumOfPoint;
22 public:
23     void init(int n){
24         sumOfPoint = n;
25         for(int i = 1; i <= n; i ++){
26             first[i] = -1;
27         }
28         sign = 0;
29     }
30     void addEdgeOneWay(int u, int v, int w){
31         edge[sign].dist = w;
32         edge[sign].to = v;
33         edge[sign].next = first[u];
34         first[u] = sign ++;
35     }
36     void addEdgeTwoWay(int u, int v, int w){
37         addEdgeOneWay(u, v, w);
38         addEdgeOneWay(v, u, w);
39     }
40     bool spfaNegRing(int start){
41         bool *vis = new bool[sumOfPoint+1];
42         int *dist = new int[sumOfPoint+1];
43         int *cnt = new int[sumOfPoint+1];
44         for(int i = 1; i <= sumOfPoint; i ++){
45             vis[i] = 0;
46             cnt[i] = 0;
47             dist[i] = INF;
48         }
49         deque<int> que;
50         que.push_front(start);
51         dist[start] = 0;
52         vis[start] = 1;
53         while(!que.empty()){
54             int now = que.front();
55             que.pop_front();
56             vis[now] = 0;
57             for(int i = first[now]; i != -1; i = edge[i].next){
58                 int to = edge[i].to, eDist = edge[i].dist;
59                 if(dist[now] + eDist < dist[to]){
60                     dist[to] = dist[now] + eDist;
61                     cnt[to] ++;
62                     if(cnt[to] >= sumOfPoint) { /// 如果这个点已经松弛n次则它必定是负环中的一个点
63                         delete []vis; delete []dist; return true;
64                     }
65                     if(!vis[to]){
66                         vis[to] = 1;
67                         if(que.empty() || dist[to] <= dist[que.front()])
68                             que.push_front(to);
69                         else
70                             que.push_back(to);
71                     }
72                 }
73             }
74         }
75         delete []vis; delete []dist; return false;
76     }
77 }graph;
78
79 int main(){
80     int f;
81     scanf("%d", &f);
82     while(f --){
83         int n, m, w;
84         scanf("%d%d%d", &n, &m, &w);
85         graph.init(n);
86         while(m --){
87             int s, e, t;
88             scanf("%d%d%d", &s, &e, &t);
89             graph.addEdgeTwoWay(s, e, t);
90         }
91         while(w --){
92             int s, e, t;
93             scanf("%d%d%d", &s, &e, &t);
94             graph.addEdgeOneWay(s, e, -t);
95         }
96         printf("%s\n", graph.spfaNegRing(1) ? "YES" : "NO");
97     }
98     return 0;
99 }

原文地址:https://www.cnblogs.com/DarkScoCu/p/10527359.html

时间: 2024-10-11 13:23:18

poj 3259 Wormholes spfa : 双端队列优化 判负环 O(k*E)的相关文章

POJ 3259 Wormholes SPFA算法题解

本题其实也可以使用SPFA算法来求解的,不过就一个关键点,就是当某个顶点入列的次数超过所有顶点的总数的时候,就可以判断是有负环出现了. SPFA原来也是可以处理负环的. 不过SPFA这种处理负环的方法自然比一般的Bellman Ford算法要慢点了. #include <stdio.h> #include <string.h> #include <limits.h> const int MAX_N = 501; const int MAX_M = 2501; const

Vijos1834 NOI2005 瑰丽华尔兹 动态规划 单调双端队列优化

设dp[t][x][y]表示处理完前t个时间段,钢琴停留在(x,y)处,最多可以走多少个格子 转移时只需逆着当前倾斜的方向统计len个格子(len为时间区间的长度,len=t-s+1),如果遇到障碍就中断 转移过程可以用单调非递增的双端队列优化 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int maxN=202; 6 const int inf=0x3f3f3f3f

[ACM] POJ 3259 Wormholes (bellman-ford最短路径,判断是否存在负权回路)

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 29971   Accepted: 10844 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way p

ACM: POJ 3259 Wormholes - SPFA负环判定

POJ 3259 Wormholes Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way pa

POJ 3259 Wormholes(SPFA判负环)

题目链接:http://poj.org/problem?id=3259 题目大意是给你n个点,m条双向边,w条负权单向边.问你是否有负环(虫洞). 这个就是spfa判负环的模版题,中间的cnt数组就是记录这个点松弛进队的次数,次数超过点的个数的话,就说明存在负环使其不断松弛. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using na

(双端队列优化的SPFA) bzoj 2100

Description Bessie has two crisp red apples to deliver to two of her friends in the herd. Of course, she travels the C (1 <= C <= 200,000) cowpaths which are arranged as the usual graph which connects P (1 <= P <= 100,000) pastures convenientl

poj 3259 Wormholes(spfa)

#include<stdio.h> #include<queue> #include<string.h> #include<algorithm> using namespace std; const int inf=0x3f3f3f3f; const int N=1024; struct node { int to; int w; node *next; }; node* edge[N]; int n,m,w,cnt[N],vis[N],dist[N]; q

POJ 3259 Wormholes (图论---最短路 Bellman-Ford || SPFA)

链接:http://poj.org/problem?id=3259 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BE

POJ 3259 Wormholes(SPFA)

Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Eac