【图论】网络流算法入门

(决定狠狠加训图论了,从一直想学但没启动的网络流算法开始。)

网络流问题

问题定义:在带权有向图 G = ( V , E ) G=(V, E) G=(V,E) 中,每条边 e = ( u , v ) e=(u, v) e=(u,v) 有容量 c ( u , v ) c(u, v) c(u,v),求从源点 s s s 到汇点 t t t 的最大流量。

1. 最大流 = 最小割定理

最小割的定义
割(Cut)是将图 G G G 的顶点分为两个不相交集合 S S S T T T,其中 s ∈ S s \in S sS t ∈ T t \in T tT
割的容量是 所有从 S S S T T T 的边的容量之和,即: 容量 ( S , T ) = ∑ u ∈ S , v ∈ T c ( u , v ) \text{容量}(S, T) = \sum_{u \in S, v \in T} c(u, v) 容量(S,T)=uS,vTc(u,v)
最大流-最小割定理
在任何网络中,最大流的值等于最小割的容量
直观理解
• 流量受限于网络中“最窄的瓶颈”,即最小割的容量。
• 最大流无法超过任何割的容量,而存在至少一个割的容量等于最大流。

证明思路

  1. 弱对偶性:最大流 ≤ 最小割(显然成立)。
  2. 强对偶性:通过构造残留网络,证明存在一个割的容量等于最大流。
    当算法终止时,残留网络中 s s s 能到达的顶点集合 S S S,其余为 T T T,此时 S S S T T T 的边流量饱和,容量等于最大流。

2. 残留网络与反向边

残留网络 G f G_f Gf
• 对每条边 e = ( u , v ) e=(u, v) e=(u,v),定义其反向边 e ′ = ( v , u ) e'=(v, u) e=(v,u),容量为当前流量 f ( u , v ) f(u, v) f(u,v)
• 残留容量:
c f ( u , v ) = c ( u , v ) − f ( u , v ) , c f ( v , u ) = f ( u , v ) c_f(u, v) = c(u, v) - f(u, v), \quad c_f(v, u) = f(u, v) cf(u,v)=c(u,v)f(u,v),cf(v,u)=f(u,v)
作用:允许“退回”流量,寻找更优路径。

增广路径
在残留网络 G f G_f Gf 中找到一条从 s s s t t t 的路径,路径上的最小残留容量称为 增广量
通过增加该路径的流量,逐步逼近最大流。


3. 费用流问题

问题定义
在最大流问题的基础上,每条边 e = ( u , v ) e=(u, v) e=(u,v) 有一个单位流量费用 w ( u , v ) w(u, v) w(u,v),求在最大流的前提下,总费用最小的流。

关键思想
最小费用最大流:优先选择费用最小的增广路径。
算法扩展
Successive Shortest Path (SSP):每次用SPFA/Bellman-Ford找最短路增广。
Primal-Dual:结合Dijkstra和势函数处理负权边。
Cost-Scaling:通过缩放费用值优化效率。

费用流的反向边处理
反向边的费用为 − w ( u , v ) -w(u, v) w(u,v),表示退回流量时费用被抵消。


算法模板:

1. Dinic算法

原理

  1. 分层图:通过BFS构建层次图(将节点按到源点的最短距离分层)。
  2. 阻塞流:在分层图上用DFS找增广路径,并通过“当前弧优化”跳过无效边。
  3. 多路增广:允许一次DFS找到多条增广路径,减少递归次数。
    时间复杂度 O ( n 2 m ) O(n^2 m) O(n2m),实际表现优秀,适合大多数场景。
    适用问题最大流问题,在稠密图和稀疏图中均表现良好。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define int long long
#define pb push_back
#define pii pair<int, int>
#define FU(i, a, b) for (int i = (a); i <= (b); ++i)
#define FD(i, a, b) for (int i = (a); i >= (b); --i)
const int MOD = 1e9 + 7;const int inf = 1e18;      // 表示无穷大的容量
const int maxn = 1e5 + 10; // 最大节点数// 边的结构体
struct edge {int from, to; // 边的起点和终点int cap;      // 边的容量int flow;     // 边当前的流量edge(int u, int v, int c, int f) : from(u), to(v), cap(c), flow(f) {}
};// Dinic算法实现类
struct Dinic {int n, m;           // 节点数、边数int s, t;           // 源点、汇点vector<edge> edges; // 所有边的集合,边数两倍(包含反向边)vector<int> G[maxn]; // 邻接表,G[i]保存节点i的所有边在edges中的索引bool vis[maxn]; // BFS使用的访问标记数组int d[maxn];    // 层次网络中各节点的层次(距离)int cur[maxn]; // 当前弧优化数组,记录每个节点当前处理的边void init(int n) { // 初始化,n为节点数this->n = n;for (int i = 0; i < n; i++)G[i].clear();edges.clear();}// 清空所有边的流量,用于多次计算不同流的情况void clear() {for (int i = 0; i < edges.size(); i++)edges[i].flow = 0;}// 将边的容量减去已使用的流量,用于调整残余网络void reduce() {for (int i = 0; i < edges.size(); i++)edges[i].cap -= edges[i].flow;}// 添加一条从from到to,容量为cap的有向边及其反向边void addedge(int from, int to, int cap) {edges.push_back(edge(from, to, cap, 0)); // 正向边,初始流量0edges.push_back(edge(to, from, 0, 0)); // 反向边,初始容量0,流量0m = edges.size();G[from].push_back(m - 2); // 记录正向边在edges中的索引G[to].push_back(m - 1);   // 记录反向边在edges中的索引}// BFS构建层次网络,返回是否存在从s到t的路径bool BFS() {memset(vis, 0, sizeof(vis));queue<int> Q;Q.push(s); // 源点入队vis[s] = true;d[s] = 0;while (!Q.empty()) {int x = Q.front();Q.pop();for (int i = 0; i < G[x].size(); i++) { // 遍历x的所有邻接边edge &e = edges[G[x][i]];// 若边的终点未访问,且仍有剩余容量if (!vis[e.to] && e.cap > e.flow) {vis[e.to] = true;d[e.to] = d[x] + 1; // 层次+1Q.push(e.to);}}}return vis[t]; // 返回汇点是否可达}// DFS寻找增广路径,x为当前节点,a为当前路径上的最小剩余容量int DFS(int x, int a) {if (x == t || a == 0) // 若到达汇点或剩余容量为0,直接返回return a;int flow = 0, f;// 使用当前弧优化,避免重复访问已经处理过的边for (int &i = cur[x]; i < G[x].size(); i++) {edge &e = edges[G[x][i]];// 层次递增且存在剩余容量if (d[x] + 1 == d[e.to] &&(f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {e.flow += f;                  // 更新正向边流量edges[G[x][i] ^ 1].flow -= f; // 反向边流量减少(允许反向增广)flow += f;                    // 累加到总流量a -= f;                       // 剩余容量减少if (a == 0)break; // 剩余容量为0,无需继续搜索}}if (flow == 0)d[x] = -2; // 炸点优化return flow;}// 计算从s到t的最大流int Maxflow(int s, int t) {this->s = s;this->t = t;int flow = 0;while (BFS()) {                  // 每次BFS构建层次网络memset(cur, 0, sizeof(cur)); // 重置当前弧flow += DFS(s, inf);         // 进行多路增广,累加流量}return flow;}// 返回最小割的边集合(需在Maxflow之后调用)vector<int> Mincut() {vector<int> ans;for (int i = 0; i < edges.size(); i++) {edge &e = edges[i];// 若边的起点在层次网络中可达,终点不可达,且为原始正向边if (vis[e.from] && !vis[e.to] && e.cap > 0)ans.push_back(i);}return ans;}
} dinic;signed main() {cin.tie(0)->ios::sync_with_stdio(0);int n, m, s, t;cin >> n >> m >> s >> t;dinic.init(n + 5); // 初始化Dinic结构体while (m--) {int s, t, u;cin >> s >> t >> u;dinic.addedge(s, t, u); // 添加边}// 计算从节点s到节点t的最大流cout << dinic.Maxflow(s, t);return 0;
}

2. ISAP算法(Improved Shortest Augmenting Path)

原理

  1. 动态分层:初始BFS分层后,逆向维护层次值(从汇点开始更新)。
  2. 重贴标签:当某层节点耗尽时,调整节点层次(类似最大流中的GAP优化)。
  3. 单次BFS:仅需一次BFS初始化,后续通过回溯调整层次,减少重复分层。
    时间复杂度 O ( n 2 m ) O(n^2 m) O(n2m),常数优于Dinic,适合大规模稀疏图。
    适用问题最大流问题,尤其适合边数较多的图。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <queue>
#include <ctime>
using namespace std;
const int maxn = 1100;
const int maxedges = 51000;
const int inf = 1 << 30;
struct edge {int to, flow;edge *next, *pair;edge() {}edge(int to, int flow, edge *next) : to(to), flow(flow), next(next) {}void *operator new(unsigned, void *p) { return p; }
};
struct ISAP {int gap[maxn], h[maxn], n, s, t;edge *cur[maxn], *first[maxn], edges[maxedges * 2], *ptr;void init(int n) {this->n = n;ptr = edges;memset(first, 0, sizeof(first));memset(gap, 0, sizeof(gap));memset(h, 0, sizeof(h));gap[0] = n;}void add_edge(int from, int to, int cap) {first[from] = new(ptr++)edge(to, cap, first[from]);first[to] = new(ptr++)edge(from, 0, first[to]);first[from]->pair = first[to];first[to]->pair = first[from];}int augment(int x, int limit) {if (x == t)return limit;int rest = limit;for (edge*& e = cur[x]; e; e = e->next) if (e->flow && h[e->to] + 1 == h[x]) {int d = augment(e->to, min(rest, e->flow));e->flow -= d, e->pair->flow += d, rest -= d;if (h[s] == n || !rest)return limit - rest;}int minh = n;for (edge *e = cur[x] = first[x]; e; e = e->next) if (e->flow)minh = min(minh, h[e->to] + 1);if (--gap[h[x]] == 0)h[s] = n;else++gap[h[x] = minh];return limit - rest;}int solve(int s, int t, int limit = inf) {this->s = s; this->t = t;memcpy(cur, first, sizeof(first)); // memcpy!int flow = 0;while (h[s] < n && flow < limit)flow += augment(s, limit - flow);return flow;}
}isap;
int main()
{freopen("D:\\in.txt", "r", stdin);int n, m;scanf("%d %d", &n, &m);isap.init(n + 5);while (m--){int s, t, u;scanf("%d %d %d", &s, &t, &u);isap.add_edge(s, t, u);}auto start = clock();printf("%d\n", isap.solve(1, n));double tot = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;printf("Isap: %f\n", tot);return 0;
}

3. HLPP算法(Highest Label Preflow Push)

原理

  1. 预流推进:允许节点暂时超额流量,通过“推进”操作将流量推向汇点。
  2. 最高标号优先:优先处理层次高的活跃节点,用优先队列维护。
  3. GAP优化:当层次出现断层时,直接标记断层上方节点为不可达。
    时间复杂度 ( O ( n 2 m ) ) (O(n^2 \sqrt{m})) (O(n2m )),理论最优,适合超大规模数据。
    适用问题最大流问题,在特定题目中比Dinic/ISAP快数倍。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <ctime>
using namespace std;
const int maxn = 2e5 + 5, maxedges = 4e6 + 5, inf = 0x3f3f3f3f;
int n, m, s, t, tot;
int v[maxedges * 2], w[maxedges * 2], first[maxn], nxt[maxedges * 2];
int h[maxn], e[maxn], gap[maxn * 2], inq[maxn];//节点高度是可以到达2n-1的
struct cmp{inline bool operator()(int a, int b) const {return h[a] < h[b];//因为在优先队列中的节点高度不会改变,所以可以直接比较}
};
queue<int> Q;
priority_queue<int, vector<int>, cmp> heap;
inline void add_edge(int from, int to, int flow) {tot += 2;v[tot + 1] = from; v[tot] = to; w[tot] = flow; w[tot + 1] = 0;nxt[tot] = first[from]; first[from] = tot;nxt[tot + 1] = first[to]; first[to] = tot + 1;return;
}
inline bool bfs() {memset(h + 1, 0x3f, sizeof(int) * n);h[t] = 0; Q.push(t);while (!Q.empty()){int now = Q.front(); Q.pop();for (int go = first[now]; go; go = nxt[go])if (w[go ^ 1] && h[v[go]] > h[now] + 1)h[v[go]] = h[now] + 1, Q.push(v[go]);}return h[s] != inf;
}
inline void push(int now) {for (int go = first[now]; go; go = nxt[go]) {if (w[go] && h[v[go]] + 1 == h[now]) {int d = min(e[now], w[go]);w[go] -= d; w[go ^ 1] += d; e[now] -= d; e[v[go]] += d;if (v[go] != s && v[go] != t && !inq[v[go]])heap.push(v[go]), inq[v[go]] = 1;if (!e[now])//已经推送完毕可以直接退出break;}}
}
inline void relabel(int now) {h[now] = inf;for (int go = first[now]; go; go = nxt[go])if (w[go] && h[v[go]] + 1 < h[now])h[now] = h[v[go]] + 1;return;
}
inline int hlpp() {int now, d;if (!bfs()) //s和t不连通return 0;h[s] = n;memset(gap, 0, sizeof(int) * (n * 2));for (int i = 1; i <= n; i++)if (h[i] < inf)++gap[h[i]];for (int go = first[s]; go; go = nxt[go]) {if (d = w[go]) {w[go] -= d; w[go ^ 1] += d; e[s] -= d; e[v[go]] += d;if (v[go] != s && v[go] != t && !inq[v[go]])heap.push(v[go]), inq[v[go]] = 1;}}while (!heap.empty()) {inq[now = heap.top()] = 0; heap.pop(); push(now);if (e[now]) {if (!--gap[h[now]]) //gap优化,因为当前节点是最高的所以修改的节点一定不在优先队列中,不必担心修改对优先队列会造成影响for (int i = 1; i <= n; i++)if (i != s && i != t && h[i] > h[now] && h[i] < n + 1)h[i] = n + 1;relabel(now); ++gap[h[now]];heap.push(now); inq[now] = 1;}}return e[t];
}
int main()
{freopen("D:\\in.txt", "r", stdin);scanf("%d %d", &n, &m); s = 1; t = n;while (m--){int s, t, u;scanf("%d %d %d", &s, &t, &u);add_edge(s, t, u);}auto start = clock();printf("%d\n", hlpp());double tot = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;printf("HLPP: %f\n", tot);return 0;
}

4. MCMF-SPFA

原理

  1. SPFA找最短路:每次用SPFA(队列优化的Bellman-Ford)找费用最小的增广路。
  2. 沿最短路增广:在最短路径上调整流量并更新残余网络。
    特点
    • 支持负权边,但SPFA可能被卡到 O ( n m ) O(nm) O(nm)
    • 适合费用流中存在负权但边数较少的图。
    适用问题最小费用最大流问题(费用流)。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <ctime>
using namespace std;
const int maxn = 20100;
const int inf = 1 << 30;
struct edge {int from, to, cap, flow, cost;edge(int u, int v, int c, int f, int w) : from(u), to(v), cap(c), flow(f), cost(w) {}
};
struct MCMF {int n, m;vector<edge> edges;vector<int> G[maxn];int inq[maxn];int d[maxn];int p[maxn];int a[maxn];void init(int n) {this->n = n;for (int i = 0; i < n; ++i)G[i].clear();edges.clear();}void add_edge(int from, int to, int cap, int cost) {edges.push_back(edge(from, to, cap, 0, cost));edges.push_back(edge(to, from, 0, 0, -cost));m = edges.size();G[from].push_back(m - 2);G[to].push_back(m - 1);}bool BellmanFord(int s, int t, int &flow, int &cost, int limit) {for (int i = 0; i < n; ++i)d[i] = inf;memset(inq, 0, sizeof(inq));d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = inf;queue<int> Q;Q.push(s);while (!Q.empty()) {int u = Q.front(); Q.pop();inq[u] = false;for (unsigned i = 0; i < G[u].size(); ++i) {edge &e = edges[G[u][i]];if (e.cap > e.flow && d[e.to] > d[u] + e.cost) {d[e.to] = d[u] + e.cost;p[e.to] = G[u][i];a[e.to] = min(a[u], e.cap - e.flow);if (!inq[e.to]) {Q.push(e.to);inq[e.to] = true;}}}}if (d[t] == inf)return false;a[t] = min(a[t], limit - flow);flow += a[t];cost += d[t] * a[t];for (int u = t; u != s; u = edges[p[u]].from) {edges[p[u]].flow += a[t];edges[p[u] ^ 1].flow -= a[t];}return true;}int solve(int s, int t, int limit = inf) {int flow = 0, cost = 0;while (flow < limit && BellmanFord(s, t, flow, cost, limit));return cost;}
}mcmf;
int main()
{freopen("D:\\in.txt", "r", stdin);int n, m, k;scanf("%d %d %d", &n, &m, &k);mcmf.init(n + 10);for (int i = 1; i <= m; ++i) {int x, y, c, w;scanf("%d %d %d %d", &x, &y, &c, &w);mcmf.add_edge(x, y, c, w);}auto start = clock();printf("%d\n", mcmf.solve(1, n, k));double tot = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;printf("MCMF-spfa: %f\n", tot);return 0;
}

5. MCMF-Dijkstra

原理

  1. 势函数去负权:通过势函数 h ( u ) h(u) h(u)调整边权,使得所有边权非负。
  2. Dijkstra找最短路:用Dijkstra代替SPFA,时间复杂度更稳定。
  3. 势函数更新:每次增广后更新势函数,保持边权非负。
    时间复杂度 O ( f m log ⁡ n ) O(f m \log n) O(fmlogn) f f f为最大流量,适合正权图。
    适用问题最小费用最大流问题,且图中无负权或通过势函数消除负权。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <ctime>
using namespace std;
const int maxn = 21000;
const int inf = 1 << 30;
struct edge {int to, cap, cost, rev;edge() {}edge(int to, int cap, int cost, int rev) : to(to), cap(cap), cost(cost), rev(rev) {}
};
struct MCMF {int n, h[maxn], d[maxn], pre[maxn], num[maxn];vector<edge> G[maxn];void init(int n) {this->n = n;for (int i = 0; i <= n; ++i)G[i].clear();}void add_edge(int from, int to, int cap, int cost) {G[from].push_back(edge(to, cap, cost, G[to].size()));G[to].push_back(edge(from, 0, -cost, G[from].size() - 1));}//flow是自己传进去的变量,就是最后的最大流,返回的是最小费用int solve(int s, int t, int &flow, int limit = inf) {int cost = 0; memset(h, 0, sizeof(h));while (limit) {priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>> > Q;for (int i = 0; i <= n; ++i)d[i] = inf;d[s] = 0; Q.emplace(0, s);while (!Q.empty()) {auto now = Q.top(); Q.pop();int u = now.second;if (d[u] < now.first) continue;for (int i = 0; i < G[u].size(); ++i) {edge &e = G[u][i];if (e.cap > 0 && d[e.to] > d[u] + e.cost + h[u] - h[e.to]) {d[e.to] = d[u] + e.cost + h[u] - h[e.to];pre[e.to] = u;num[e.to] = i;Q.emplace(d[e.to], e.to);}}}if (d[t] == inf) break;for (int i = 0; i <= n; ++i)h[i] += d[i];int a = limit;for (int u = t; u != s; u = pre[u])a = min(a, G[pre[u]][num[u]].cap);limit -= a; flow += a; cost += a * h[t];for (int u = t; u != s; u = pre[u]) {edge &e = G[pre[u]][num[u]];e.cap -= a;G[u][e.rev].cap += a;}}return cost;}
}mcmf;
int main()
{freopen("D:\\in.txt", "r", stdin);int n, m, k, flow = 0;scanf("%d %d %d", &n, &m, &k);mcmf.init(n + 10);for (int i = 1; i <= m; ++i) {int x, y, c, w;scanf("%d %d %d %d", &x, &y, &c, &w);mcmf.add_edge(x, y, c, w);}auto start = clock();printf("%d\n", mcmf.solve(1, n, flow, k));printf("flow: %d\n", flow);double tot = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;printf("MCMF-dijkstra: %f\n", tot);return 0;
}

(代码来自孙明志大佬的xcpc算法模板)


总结

最大流问题:优先选择DinicISAP(代码简单),超大规模数据用HLPP
费用流问题
• 含负权边 → MCMF-SPFA
• 无负权边 → MCMF-Dijkstra(更高效)。
关键区别
• Dinic/ISAP/HLPP解决最大流,MCMF类解决费用流。
• SPFA允许负权但慢,Dijkstra需正权但快;HLPP通过预流推进优化最大流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/73508.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

递归、搜索与回溯第四讲:floodfill算法

递归、搜索与回溯第四讲&#xff1a;floodfill算法 1.Floodfill算法介绍2.图像渲染3.岛屿数量4.岛屿的最大面积5.被围绕的区域6.太平洋大西洋水流问题7.扫雷游戏8.衣橱整理 1.Floodfill算法介绍 2.图像渲染 3.岛屿数量 4.岛屿的最大面积 5.被围绕的区域 6.太平洋大西洋水流问题…

【深度学习与实战】2.3、线性回归模型与梯度下降法先导案例--最小二乘法(向量形式求解)

为了求解损失函数 对 的导数&#xff0c;并利用最小二乘法向量形式求解 的值‌ 这是‌线性回归‌的平方误差损失函数&#xff0c;目标是最小化预测值 与真实值 之间的差距。 ‌损失函数‌&#xff1a; 考虑多个样本的情况&#xff0c;损失函数为所有样本的平方误差之和&a…

气象可视化卫星云图的方式:方法与架构详解

气象卫星云图是气象预报和气候研究的重要数据来源。通过可视化技术,我们可以将卫星云图数据转化为直观的图像或动画,帮助用户更好地理解气象变化。本文将详细介绍卫星云图可视化的方法、架构和代码实现。 一、卫星云图可视化方法 1. 数据获取与预处理 卫星云图数据通常来源…

浏览器渲染原理与优化详解

一、浏览器渲染基础原理 浏览器渲染流程主要包括以下步骤&#xff08;也称为"关键渲染路径"&#xff09;&#xff1a; 构建DOM树&#xff1a;将HTML解析为DOM&#xff08;文档对象模型&#xff09;树构建CSSOM树&#xff1a;将CSS解析为CSSOM&#xff08;CSS对象模…

基于Spring Boot的成绩管理系统后台实现

下面是一个完整的成绩管理系统后台实现&#xff0c;使用Spring Boot框架&#xff0c;包含学生管理、课程管理和成绩管理功能。 1. 项目结构 src/main/java/com/example/grademanagement/ ├── config/ # 配置类 ├── controller/ # 控制器 ├── dto/ …

实现极限网关(INFINI Gateway)配置动态加载

还在停机更新 Gateway 配置&#xff0c;OUT 了。 今天和大家分享一个 Gateway 的功能&#xff1a;动态加载配置&#xff08;也称热更新或热加载&#xff09;。 这个功能可以在 Gateway 不停机的情况下更新配置并使之生效。 配置样例如下&#xff1a; path.data: data path.…

Mean Shift 图像分割与 Canny 边缘检测教程

1. Mean Shift 简介 Mean Shift 是一种聚类算法&#xff0c;通过寻找图像中颜色相似的区域来实现分割。它非常适合用于场景分割或物体检测等任务。本教程将它与 Canny 边缘检测结合&#xff0c;突出分割区域的边界。 2. 图像分割流程 我们将按照以下步骤完成图像分割和边缘检…

Day15 -实例 端口扫描工具 WAF识别工具的使用

一、端口扫描工具 1、zenmap 我这里user是汉字名&#xff0c;没有解析成功。等后续换一个英文账户试一试。 魔改kali的nmap nmap -p8000-9000 8.140.159.19 2、masscan cmd启动&#xff0c;拖入exe文件。然后先写ip&#xff0c;会报错给提示 寻路犬系统 我们去找一下他的…

如何解决高并发场景下的性能瓶颈?实践分享

解决高并发性能瓶颈的核心方法包括优化系统架构、合理使用缓存技术、数据库优化及扩展策略、负载均衡设计。 其中&#xff0c;优化系统架构是根本解决性能问题的关键所在。良好的系统架构能够有效支撑业务高效稳定运行&#xff0c;避免性能瓶颈带来的损失。企业可通过微服务架构…

自动驾驶背后的数学:ReLU,Sigmoid, Leaky ReLU, PReLU,Swish等激活函数解析

随着自动驾驶技术的飞速发展&#xff0c;深度学习在其中扮演着至关重要的角色。而激活函数作为神经网络中的关键组件&#xff0c;直接影响着模型的性能和效果。前面几篇博客 自动驾驶背后的数学&#xff1a;特征提取中的线性变换与非线性激活 , 「自动驾驶背后的数学&#xff1…

性能测试、负载测试、压力测试的全面解析

在软件测试领域&#xff0c;性能测试、负载测试和压力测试是评估系统稳定性和可靠性的关键手段。​它们各自关注不同的测试目标和应用场景&#xff0c;理解这些差异对于制定有效的测试策略至关重要。 本文对性能测试、负载测试和压力测试进行深入分析&#xff0c;探讨其定义、…

责任链模式-java

1、spring依赖注入模式 @Configuration public class ChainConfig {@Beanpublic ChainSpringFactory chainSpringFactory(List<IHandler<DemoOne,Boolean>> handlerList){return new ChainSpringFactory(handlerList);}} public class DemoOne { }public abstract…

学习本地部署DeepSeek的过程(基于LM Studio)

除了使用Ollama部署DeepSeek&#xff0c;还可以使用LM Studio部署DeepSeek&#xff0c;后者是一款允许用户在本地计算机上运行大型语言模型&#xff08;LLMs&#xff09;的桌面应用程序&#xff0c;旨在简化本地模型的使用&#xff0c;无需云端连接或复杂配置即可体验 AI 功能。…

CSS 尺寸 (Dimension)

CSS 尺寸 (Dimension) 在网页设计中&#xff0c;CSS&#xff08;层叠样式表&#xff09;的尺寸属性是控制元素大小和位置的关键。本文将详细介绍CSS尺寸相关的概念、属性及其应用。 1. CSS 尺寸概述 CSS尺寸主要包括宽度和高度&#xff0c;这些属性可以应用于各种HTML元素&a…

【自学笔记】ELK基础知识点总览-持续更新

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 ELK基础知识点总览1. ELK简介2. Elasticsearch基础Elasticsearch配置示例&#xff08;elasticsearch.yml&#xff09; 3. Logstash基础Logstash配置示例&#xff08…

等差数列公式推导

前言&#xff1a; 通过实践而发现真理&#xff0c;又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识&#xff0c;又从理性认识而能动地指导革命实践&#xff0c;改造主观世界和客观世界。实践、认识、再实践、再认识&#xff0c;这种形式&#xff0c;循环往…

【MySQL】用户账户、角色、口令、PAM

目录 查看用户账户设置 连接 1.本地连接 2.远程连接 账户 角色 操作用户账户和角色 配置口令和账户有效期限 手工使口令过期 配置口令有效期限 PAM身份验证插件 客户端连接&#xff1a;使用 PAM 账户登录 在连接到MySQL服务器并执行查询时&#xff0c;会验证你的身…

5种生成模型(VAE、GAN、AR、Flow 和 Diffusion)的对比梳理 + 易懂讲解 + 代码实现

目录 1 变分自编码器&#xff08;VAE&#xff09;​ 1.1 概念 1.2 训练损失 1.3 VAE 的实现 2 生成对抗网络&#xff08;GAN&#xff09;​ 2.1 概念 2.2 训练损失 a. 判别器的损失函数 b. 生成器的损失函数 c. 对抗训练的动态过程 2.3 GAN 的实现 3 自回归模型&am…

印刷电路板 (PCB) 的影响何时重要?在模拟环境中导航

我和我的同事们经常被问到关于 PCB 效应的相同问题&#xff0c;例如&#xff1a; 仿真何时需要 PCB 效果&#xff1f; 为什么时域仿真需要 PCB 效应&#xff1f; 当 PCB 效应必须包含在仿真中时&#xff0c;频率是否重要&#xff1f; 设计人员应该在多大程度上关注 VRM 模型中包…

2024跨境电商挑战:AI反检测技术在避免封号中的作用

2024跨境电商挑战&#xff1a;AI反检测技术在避免封号中的作用 跨境电商的浪潮席卷全球&#xff0c;为商家打开了通往世界各地的大门。然而&#xff0c;随着平台监管的加强&#xff0c;合规性问题成为商家不得不面对的挑战。在电商平台的严格监控下&#xff0c;任何违规行为都…