[網路流24題]P4014 分配問題+ P4015 運輸問題
阿新 • • 發佈:2021-10-21
費用流模板題(怎麼全是費用流啊?)
https://www.luogu.com.cn/problem/P4014
https://www.luogu.com.cn/problem/P4015
P4014
#include <algorithm> #include <cmath> #include <cstdio> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <set> #include <sstream> #include <vector> #define endl '\n' #define IOS \ ios::sync_with_stdio(0); \ cin.tie(0); \ cout.tie(0); #define P pair<int, int> typedef long long ll; using namespace std; typedef long long ll; const int maxn = 220; const ll inf = 1e18; int n, cnt_edge = 1, S, T; int a1[maxn], a2[maxn], head[maxn]; ll dis[maxn]; bool vis[maxn]; struct edge { int to, nxt; ll flow, cost; } e[(maxn * maxn) << 2]; inline void add(int u, int v, ll w, ll c) { e[++cnt_edge].nxt = head[u]; head[u] = cnt_edge; e[cnt_edge].to = v; e[cnt_edge].flow = w; e[cnt_edge].cost = c; } inline void addflow(int u, int v, ll w, ll c) { add(u, v, w, c); add(v, u, 0, -c); } inline bool spfa(int on) { memset(vis, 0, sizeof(vis)); if (on == 1) for (int i = 0; i <= T; i++) dis[i] = inf; else for (int i = 0; i <= T; i++) dis[i] = -inf; queue<int> q; q.push(S); dis[S] = 0; vis[S] = 1; while (!q.empty()) { int x = q.front(); q.pop(); vis[x] = 0; for (int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; // cout << "->" << y << endl; if ((on == 1 && e[i].flow && dis[y] > dis[x] + e[i].cost) || (on == -1 && e[i].flow && dis[y] < dis[x] + e[i].cost)) { dis[y] = dis[x] + e[i].cost; if (!vis[y]) q.push(y), vis[y] = 1; } } } if (on == 1) return dis[T] != inf; else return dis[T] != -inf; } ll dfs(int x, ll lim) { vis[x] = 1; if (x == T || lim <= 0) return lim; ll res = lim; for (int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; if (dis[y] != dis[x] + e[i].cost || e[i].flow <= 0 || vis[y]) continue; ll tmp = dfs(y, min(res, e[i].flow)); res -= tmp; e[i].flow -= tmp; e[i ^ 1].flow += tmp; if (res <= 0) break; } return lim - res; } inline ll Dinic(int on) { ll res = 0, cost = 0; while (spfa(on)) { ll flow = dfs(S, inf); res += flow, cost += flow * dis[T]; } return cost; } int main() { cin >> n; S = n + n + 1, T = n + n + 2; for (int i = 1; i <= n; i++) { addflow(S, i, 1, 0); addflow(n + i, T, 1, 0); } for (int i = 1, c; i <= n; i++) { for (int j = 1; j <= n; j++) { cin >> c; addflow(i, j + n, inf, c); } } cout << Dinic(1)<<endl; for (int i = 0; i < cnt_edge; i+=2) { e[i].flow += e[i ^ 1].flow; e[i ^ 1].flow = 0; } cout << Dinic(-1)<<endl; return 0; }
P4015
#include <algorithm> #include <cmath> #include <cstdio> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <set> #include <sstream> #include <vector> #define endl '\n' #define IOS \ ios::sync_with_stdio(0); \ cin.tie(0); \ cout.tie(0); #define P pair<int, int> typedef long long ll; using namespace std; typedef long long ll; const int maxn = 120; const ll inf = 1e18; int n1, n2, cnt_edge = 1, S, T; int a1[maxn], a2[maxn], head[maxn]; ll dis[maxn]; bool vis[maxn]; struct edge { int to, nxt; ll flow, cost; } e[(maxn * maxn) << 2]; inline void add(int u, int v, ll w, ll c) { e[++cnt_edge].nxt = head[u]; head[u] = cnt_edge; e[cnt_edge].to = v; e[cnt_edge].flow = w; e[cnt_edge].cost = c; } inline void addflow(int u, int v, ll w, ll c) { add(u, v, w, c); add(v, u, 0, -c); } inline bool spfa(int on) { memset(vis, 0, sizeof(vis)); if (on == 1) for (int i = 0; i <= T; i++) dis[i] = inf; else for (int i = 0; i <= T; i++) dis[i] = -inf; queue<int> q; q.push(S); dis[S] = 0; vis[S] = 1; while (!q.empty()) { int x = q.front(); q.pop(); vis[x] = 0; for (int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; // cout << "->" << y << endl; if ((on == 1 && e[i].flow && dis[y] > dis[x] + e[i].cost) || (on == -1 && e[i].flow && dis[y] < dis[x] + e[i].cost)) { dis[y] = dis[x] + e[i].cost; if (!vis[y]) q.push(y), vis[y] = 1; } } } if (on == 1) return dis[T] != inf; else return dis[T] != -inf; } ll dfs(int x, ll lim) { vis[x] = 1; if (x == T || lim <= 0) return lim; ll res = lim; for (int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; if (dis[y] != dis[x] + e[i].cost || e[i].flow <= 0 || vis[y]) continue; ll tmp = dfs(y, min(res, e[i].flow)); res -= tmp; e[i].flow -= tmp; e[i ^ 1].flow += tmp; if (res <= 0) break; } return lim - res; } inline ll Dinic(int on) { ll res = 0, cost = 0; while (spfa(on)) { ll flow = dfs(S, inf); res += flow, cost += flow * dis[T]; } return cost; } int main() { cin >> n1 >> n2; S = n1 + n2 + 1, T = n1 + n2 + 2; for (int i = 1; i <= n1; i++) { cin >> a1[i]; addflow(S, i, a1[i], 0); } for (int i = 1; i <= n2; i++) { cin >> a2[i]; addflow(n1 + i, T, a2[i], 0); } for (int i = 1, c; i <= n1; i++) { for (int j = 1; j <= n2; j++) { cin >> c; addflow(i, j + n1, inf, c); } } cout << Dinic(1)<<endl; for (int i = 0; i < cnt_edge; i+=2) { e[i].flow += e[i ^ 1].flow; e[i ^ 1].flow = 0; } cout << Dinic(-1)<<endl; return 0; }