板子——SPFA/判负环

SPFA是很简单的:普通队列,用du + w更新dv即可。判断是否in queue可以提高速度。

 1 void spfa() {
 2     memset(d, 0x3f, sizeof d); d[1] = 0;
 3     q.push(1); inq[1] = true;
 4     while (!q.empty()) {
 5         int u = q.front(); q.pop();
 6         inq[u] = false;                                        //just to improve effiency
 7         for (int i = 0; i < g[u].size(); i++) {
 8             int v = g[u][i].v, w = g[u][i].w;
 9             if (d[v] > d[u] + w) {
10                 d[v] = d[u] + w;
11                 if (!inq[v]) q.push(v), inq[v] = true;
12             }
13         }
14     }
15 }

这里放上Dij加以对比:利用优先队列每次找dv最小的点,而且要避免重复访问。而当负环存在时,当下最小的dv不一定以后最小,dij不再正确。

 1 void dijkstra() {
 2   memset(d, 0x3f, sizeof d); d[1] = 0;
 3   q.push(make_pair(0, 1));
 4   while (q.size()) {
 5     int u = q.top().second; q.pop(); 6     if (vis[u]) continue;
 7     vis[u] = 1;
 8     for (int i = 0; i < g[u].size(); i++) {
 9       int v = g[u][i].v, w = g[u][i].w;
10       if (d[v] > d[u] + w) d[v] = d[u] + w, q.push(make_pair(-d[v], v));
11     }
12   } 
13 }

在SPFA中,如果从起点到某个点的当前最短路径上走过了至少n个点,说明存在负环。

 1 bool spfa() {
 2     memset(d, 0x3f, sizeof d); d[1] = 0;
 3     for (int i = 1; i <= n; i++) {
 4         q.push(i); inq[i] = 1;
 5     }
 6     while (!q.empty()) {
 7         int u = q.front(); q.pop();
 8         inq[u] = false;                                    
 9         for (int i = 0; i < g[u].size(); i++) {
10             int v = g[u][i].v, w = g[u][i].w;
11             if (d[v] > d[u] + w) {
12                 d[v] = d[u] + w;
13                 cnt[v] = cnt[u] + 1;
14                 if (cnt[v] >= n) return 1;
15                 if (!inq[v]) q.push(v), inq[v] = 1;
16             }
17         }
18     }
19     return 0;
20 }

 

logo
posted @ 2021-09-24 00:15  _vv123  阅读(37)  评论(0编辑  收藏  举报