Topic 1 Zjoi min cut
Main topic:
Ask for a minimum cut between the two points of a non-weighted graph, asking how many point pairs are less than or equal to C.
Algorithm discussion: Minimum cut and divide treatment
Code:
#include <cstdlib> #include <iostream> #include <cstring> #include <algorithm> #include < Cstdio> #include <vector> using namespace std;const int N = 5;const int M = + 5;const int oo = 0x3f3f3f 3f, #define INF oo int n, m;bool mark[n];int a[n], tmp[n], ans[n][n]; struct Edge {int from, to, cap, flow; Edge (int u = 0, int v = 0, int c = 0, int f = 0): From (U), to (v), Cap (c), Flow (f) {}}; struct Dinic {int n, mm, S, t; int dis[n], cur[n], que[n * 10]; BOOL Vis[n]; Vector <Edge> edges; Vector <int> G[n]; void Clear () {for (int i = 0; I <= N; + + i) g[i].clear (); Edges.clear (); } void Add (int from, int to, int cap) {Edges.push_back (Edge (from, to, Cap, 0)); Edges.push_back (Edge (to, from, Cap, 0)); mm = Edges.size (); G[from].push_back (mm-2); G[to].push_back (mm-1); } bool BFs () {int head = 1, tail = 1; Memset (Vis, False, (n + 1) * sizeof (BOOL)); Dis[s] = 0; Vis[s] = true; Que[head] =S while (head <= tail) {int x = Que[head]; for (int i = 0; i < (signed) g[x].size (); + + i) {Edge &e = edges[g[x][i]]; if (!vis[e.to] && e.cap > E.flow) {vis[e.to] = true; Dis[e.to] = dis[x] + 1; que[++ tail] = e.to; }} + + head; } return vis[t]; } int dfs (int x, int a) {if (x = = T | | a = = 0) return A; int FLW = 0, F; for (int &i = cur[x]; i < (signed) g[x].size (); + + i) {Edge &e = edges[g[x][i]]; if (dis[e.to] = = Dis[x] + 1 && (f = dfs (e.to, Min (A, e.cap-e.flow))) > 0) {e.flow + = f; Edges[g[x][i] ^ 1].flow-= f; FLW + = f; A-= f; if (a = = 0) break; }} return FLW; } int Maxflow (int s, int t) {this->s = s; this->t = t; int FLW = 0; while (BFS ()) {memset (cur, 0, sizeof cur); FLW + = DFS (s, oo); } return FLW; } void Rebuild () {for (int i = 0; i < (signed) edges.size (); + + i)Edges[i].flow = 0; } void Dfs (int u) {Mark[u] = true; for (int i = 0; i < (signed) g[u].size (); + + i) {Edge E = edges[g[u][i]]; if (!mark[e.to] && e.cap > E.flow) {dfs (e.to); }}}}net; void Divide (int l, int r) {if (L >= R) return; Net.rebuild (); int nowflow = Net.maxflow (A[l], a[r]); Memset (Mark, False, (n + 1) * sizeof (BOOL)); Net.dfs (A[l]); for (int i = 1; I <= n; + + i) if (Mark[i]) for (int j = 1; J <= N; + + j) if (!mark[j]) ans[i][j] = Min (ans[i][j], nowflow), ans[j][i] = ans[i][j]; int L = L, R = r; for (int i = l; I <= R; + + i) if (Mark[a[i]]) Tmp[l + +] = A[i]; Else Tmp[r--] = a[i]; for (int i = l; I <= R; + + i) a[i] = Tmp[i]; Divide (L, L-1); Divide (r + 1, r);//This cannot be two minutes because the size of the S-set and T-set is not necessarily the same} int main () {int T, u, V, c, Q; scanf ("%d", &t); while (T--) {net.clear (); scanf ("%d%d", &n, &m); NET.N = n; for (int i = 1; I <= n; + + i) a[i] = i; for (int i = 1; I <= N; + + i) for (int j = 1; J <= N; + + j) Ans[i][j] = inf; for (int i = 1; I <= m; + + i) {scanf ("%d%d%d", &u, &v, &c); Net.add (U, V, c); } Divide (1, N); scanf ("%d", &q); for (int i = 1; I <= Q; + + i) {int tmp = 0; scanf ("%d", &c); for (int u = 1; u <= N, + + u) {for (int v = u + 1; v <= N; + + V) {if (Ans[u][v] <= c) { + + tmp; }}} printf ("%d\n", TMP); } puts (""); } return 0;}
Topic 2 CQOI2016 different minimum cut
Main topic:
Ask for a different minimum cut number for all point pairs.
Algorithm discussion: Minimum cut and divide treatment
Is there a difference from one of the above questions?
Code:
#include <cstdlib> #include <iostream> #include <cstring> #include <algorithm> #include < cstdio> #include <vector> #include <set> using namespace std;const int N = 850 + 5;const int M = 8500 + 5;con St int oo = 0x3f3f3f3f; int n, M;int ans[n][n], tmp[n], a[n];bool mark[n];set <int> lts; struct Edge {int from, to, cap, flow; Edge (int u = 0, int v = 0, int cap = 0, int flow = 0): From (U), to (v), cap (CAP), flow (flow) {}}; struct Dinic {int n, m, S, t; int dis[n], cur[n], que[n * 10]; BOOL Vis[n]; Vector <Edge> edges; Vector <int> G[n]; void Add (int from, int to, int caps) {Edges.push_back (from, to, Cap, 0)); Edges.push_back (Edge (to, from, Cap, 0)); m = Edges.size (); G[from].push_back (m-2); G[to].push_back (m-1); } bool BFs () {int head = 1, tail = 1; Memset (Vis, False, (n + 1) * sizeof (BOOL)); Dis[s] = 0; Vis[s] = true; Que[head] = s; while (head <= tail) {int x = Que[head]; for (int i = 0; i < (signed) g[x].size (); + + i) {Edge &e = edges[g[x][i]]; if (!vis[e.to] && e.cap > E.flow) {vis[e.to] = true; Dis[e.to] = dis[x] + 1; que[++ tail] = e.to; }} + + head; } return vis[t]; } int dfs (int x, int a) {if (x = = T | | a = = 0) return A; int FLW = 0, F; for (int &i = cur[x]; i < (signed) g[x].size (); + + i) {Edge &e = edges[g[x][i]]; if (dis[e.to] = = Dis[x] + 1 && (f = dfs (e.to, Min (A, e.cap-e.flow))) > 0) {e.flow + = f; Edges[g[x][i] ^ 1].flow-= f; A-= f; FLW + = f; if (a = = 0) break; }} return FLW; } int Maxflow (int s, int t) {this->s = s; this->t = t; int FLW = 0; while (BFS ()) {memset (cur, 0, sizeof cur); FLW + = DFS (s, oo); } return FLW; } void Rebuild () {for (int i = 0; i < (signed) edges.size (); + + i) Edges[i].flow = 0; } void Dfs (int u) {Mark[u] = tRue for (int i = 0; i < (signed) g[u].size (); + + i) {Edge E = edges[g[u][i]]; if (!mark[e.to] && e.cap > E.flow) dfs (e.to); }}}net; void Divide (int l, int r) {if (L >= R) return; Net.rebuild (); int nowflow = Net.maxflow (A[l], a[r]); Memset (Mark, False, (n + 1) * sizeof (BOOL)); Net.dfs (A[l]); for (int i = 1; I <= n; + + i) if (Mark[i]) for (int j = 1; J <= N; + + j) if (!mark[j]) ans[i][j] = Min (ans[i][j], nowflow), ans[j][i] = ans[i][j]; int L = L, R = r; for (int i = l; I <= R; + + i) if (Mark[a[i]]) Tmp[l + +] = A[i]; Else Tmp[r--] = a[i]; for (int i = l; I <= R; + + i) a[i] = Tmp[i]; Divide (L, L-1); Divide (r + 1, r);} int main () {int u, V, c; scanf ("%d%d", &n, &m); for (int i = 1; I <= m; + + i) {scanf ("%d%d%d", &u, &v, &c); Net.add (U, V, c); } for (int i = 1; I <= n; + + i) a[i] = i; for (int i = 1; I <= n; + + i) for (int j = 1; J <= N; + + j) Ans[i][j]= OO; NET.N = n; Divide (1, N); for (int i = 1; I <= N, + + i) {for (int j = i + 1; j <= N; + + j) {Lts.insert (ans[i][j]); }} printf ("%d\n", Lts.size ()); return 0;}
Network Flow topic Pan-do (the cost flow is not written in this area)