Loading docs/graph/flow/max-flow.md +113 −137 Original line number Diff line number Diff line Loading @@ -33,43 +33,37 @@ EK 算法的时间复杂度为 $O(n^2m)$(其中 $n$ 为点数,$m$ 为边数)。效率还有很大提升空间。 ```cpp #include <algorithm> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define INF 0x3f3f3f3f using namespace std; struct edge { struct edge { int v, w, next; } e[200005]; struct node { struct node { int v, e; } p[10005]; int head[10005], vis[10005]; int n, m, s, t, cnt = 1; void addedge(int u,int v,int w) { void addedge(int u, int v, int w) { e[++cnt].v = v; e[cnt].w = w; e[cnt].next = head[u]; head[u] = cnt; } bool bfs() { bool bfs() { queue<int> q; memset(p, 0, sizeof(p)); memset(vis, 0, sizeof(vis)); vis[s] = 1; q.push(s); while(!q.empty()) { while (!q.empty()) { int cur = q.front(); q.pop(); for (int i = head[cur]; i; i = e[i].next) if((!vis[e[i].v])&&e[i].w) { if ((!vis[e[i].v]) && e[i].w) { p[e[i].v].v = cur; p[e[i].v].e = i; if (e[i].v == t) return 1; Loading @@ -79,24 +73,19 @@ bool bfs() } return 0; } int main() { int main() { scanf("%d%d%d%d", &n, &m, &s, &t); for(int i=1;i<=m;i++) { for (int i = 1; i <= m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); addedge(u, v, w); addedge(v, u, 0); } int ans = 0; while(bfs()) { while (bfs()) { int minw = INF; for(int i=t;i!=s;i=p[i].v) minw=min(minw,e[p[i].e].w); for(int i=t;i!=s;i=p[i].v) { for (int i = t; i != s; i = p[i].v) minw = min(minw, e[p[i].e].w); for (int i = t; i != s; i = p[i].v) { e[p[i].e].w -= minw; e[p[i].e ^ 1].w += minw; } Loading Loading @@ -130,27 +119,24 @@ Dinic 算法有两个优化: 特别地,在求解二分图最大匹配问题时,可以证明 Dinic 算法的时间复杂度是 $O(n \sqrt{m})$。 ```cpp #include <algorithm> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define INF 0x3f3f3f3f using namespace std; struct edge { struct edge { int v, w, next; } e[200005]; int n, m, s, t, cnt = 1; int head[100005], dep[100005], vis[100005], cur[100005]; void addedge(int u,int v,int w) { void addedge(int u, int v, int w) { e[++cnt].v = v; e[cnt].w = w; e[cnt].next = head[u]; head[u] = cnt; } bool bfs() { bool bfs() { queue<int> q; memset(dep, INF, sizeof(dep)); memset(vis, 0, sizeof(vis)); Loading @@ -158,17 +144,14 @@ bool bfs() dep[s] = 0; vis[s] = 1; q.push(s); while(!q.empty()) { while (!q.empty()) { int p = q.front(); q.pop(); vis[p] = 0; for (int i = head[p]; i; i = e[i].next) if(dep[e[i].v]>dep[p]+1&&e[i].w) { if (dep[e[i].v] > dep[p] + 1 && e[i].w) { dep[e[i].v] = dep[p] + 1; if(!vis[e[i].v]) { if (!vis[e[i].v]) { vis[e[i].v] = 1; q.push(e[i].v); } Loading @@ -177,18 +160,15 @@ bool bfs() if (dep[t] == INF) return 0; return 1; } int dfs(int p,int w) { int dfs(int p, int w) { if (p == t) return w; int used = 0; //已经使用的流量 for (int i = cur[p]; i; i = e[i].next) //每条边都尝试找一次增广路 { cur[p] = i; //当前弧优化 if(dep[e[i].v]==dep[p]+1&&e[i].w) { if (dep[e[i].v] == dep[p] + 1 && e[i].w) { int flow = dfs(e[i].v, min(w - used, e[i].w)); if(flow) { if (flow) { used += flow; e[i].w -= flow; e[i ^ 1].w += flow; Loading @@ -198,19 +178,16 @@ int dfs(int p,int w) } return used; } int main() { int main() { scanf("%d%d%d%d", &n, &m, &s, &t); for(int i=1;i<=m;i++) { for (int i = 1; i <= m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); addedge(u, v, w); addedge(v, u, 0); } int ans = 0; while(bfs()) ans+=dfs(s,INF); while (bfs()) ans += dfs(s, INF); printf("%d\n", ans); return 0; } Loading @@ -219,4 +196,3 @@ int main() ### ISAP 这个是 SAP 算法的加强版 (Improved)。 Loading
docs/graph/flow/max-flow.md +113 −137 Original line number Diff line number Diff line Loading @@ -33,43 +33,37 @@ EK 算法的时间复杂度为 $O(n^2m)$(其中 $n$ 为点数,$m$ 为边数)。效率还有很大提升空间。 ```cpp #include <algorithm> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define INF 0x3f3f3f3f using namespace std; struct edge { struct edge { int v, w, next; } e[200005]; struct node { struct node { int v, e; } p[10005]; int head[10005], vis[10005]; int n, m, s, t, cnt = 1; void addedge(int u,int v,int w) { void addedge(int u, int v, int w) { e[++cnt].v = v; e[cnt].w = w; e[cnt].next = head[u]; head[u] = cnt; } bool bfs() { bool bfs() { queue<int> q; memset(p, 0, sizeof(p)); memset(vis, 0, sizeof(vis)); vis[s] = 1; q.push(s); while(!q.empty()) { while (!q.empty()) { int cur = q.front(); q.pop(); for (int i = head[cur]; i; i = e[i].next) if((!vis[e[i].v])&&e[i].w) { if ((!vis[e[i].v]) && e[i].w) { p[e[i].v].v = cur; p[e[i].v].e = i; if (e[i].v == t) return 1; Loading @@ -79,24 +73,19 @@ bool bfs() } return 0; } int main() { int main() { scanf("%d%d%d%d", &n, &m, &s, &t); for(int i=1;i<=m;i++) { for (int i = 1; i <= m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); addedge(u, v, w); addedge(v, u, 0); } int ans = 0; while(bfs()) { while (bfs()) { int minw = INF; for(int i=t;i!=s;i=p[i].v) minw=min(minw,e[p[i].e].w); for(int i=t;i!=s;i=p[i].v) { for (int i = t; i != s; i = p[i].v) minw = min(minw, e[p[i].e].w); for (int i = t; i != s; i = p[i].v) { e[p[i].e].w -= minw; e[p[i].e ^ 1].w += minw; } Loading Loading @@ -130,27 +119,24 @@ Dinic 算法有两个优化: 特别地,在求解二分图最大匹配问题时,可以证明 Dinic 算法的时间复杂度是 $O(n \sqrt{m})$。 ```cpp #include <algorithm> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define INF 0x3f3f3f3f using namespace std; struct edge { struct edge { int v, w, next; } e[200005]; int n, m, s, t, cnt = 1; int head[100005], dep[100005], vis[100005], cur[100005]; void addedge(int u,int v,int w) { void addedge(int u, int v, int w) { e[++cnt].v = v; e[cnt].w = w; e[cnt].next = head[u]; head[u] = cnt; } bool bfs() { bool bfs() { queue<int> q; memset(dep, INF, sizeof(dep)); memset(vis, 0, sizeof(vis)); Loading @@ -158,17 +144,14 @@ bool bfs() dep[s] = 0; vis[s] = 1; q.push(s); while(!q.empty()) { while (!q.empty()) { int p = q.front(); q.pop(); vis[p] = 0; for (int i = head[p]; i; i = e[i].next) if(dep[e[i].v]>dep[p]+1&&e[i].w) { if (dep[e[i].v] > dep[p] + 1 && e[i].w) { dep[e[i].v] = dep[p] + 1; if(!vis[e[i].v]) { if (!vis[e[i].v]) { vis[e[i].v] = 1; q.push(e[i].v); } Loading @@ -177,18 +160,15 @@ bool bfs() if (dep[t] == INF) return 0; return 1; } int dfs(int p,int w) { int dfs(int p, int w) { if (p == t) return w; int used = 0; //已经使用的流量 for (int i = cur[p]; i; i = e[i].next) //每条边都尝试找一次增广路 { cur[p] = i; //当前弧优化 if(dep[e[i].v]==dep[p]+1&&e[i].w) { if (dep[e[i].v] == dep[p] + 1 && e[i].w) { int flow = dfs(e[i].v, min(w - used, e[i].w)); if(flow) { if (flow) { used += flow; e[i].w -= flow; e[i ^ 1].w += flow; Loading @@ -198,19 +178,16 @@ int dfs(int p,int w) } return used; } int main() { int main() { scanf("%d%d%d%d", &n, &m, &s, &t); for(int i=1;i<=m;i++) { for (int i = 1; i <= m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); addedge(u, v, w); addedge(v, u, 0); } int ans = 0; while(bfs()) ans+=dfs(s,INF); while (bfs()) ans += dfs(s, INF); printf("%d\n", ans); return 0; } Loading @@ -219,4 +196,3 @@ int main() ### ISAP 这个是 SAP 算法的加强版 (Improved)。