网络流模板 NetworkFlow

时间:2023-03-09 00:49:30
网络流模板 NetworkFlow

身边的小伙伴们都在愉快地刷网络流,我也来写一发模板好了。

Network Flow - Maximum Flow

Time Limit : 1 sec, Memory Limit : 65536 KB 
Japanese version is here

 #include <bits/stdc++.h>

 #define fread_siz 1024

 inline int get_c(void)
{
static char buf[fread_siz];
static char *head = buf + fread_siz;
static char *tail = buf + fread_siz; if (head == tail)
fread(head = buf, , fread_siz, stdin); return *head++;
} inline int get_i(void)
{
register int ret = ;
register int neg = false;
register int bit = get_c(); for (; bit < ; bit = get_c())
if (bit == '-')neg ^= true; for (; bit > ; bit = get_c())
ret = ret * + bit - ; return neg ? -ret : ret;
} template <class T>
inline T min(T a, T b)
{
return a < b ? a : b;
} const int inf = 2e9;
const int maxn = ; int n, m;
int s, t; int edges;
int hd[maxn];
int to[maxn];
int nt[maxn];
int fl[maxn]; inline void add(int u, int v, int f)
{
nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; hd[u] = edges++;
nt[edges] = hd[v]; to[edges] = u; fl[edges] = ; hd[v] = edges++;
} int dep[maxn]; inline bool bfs(void)
{
static int que[maxn];
static int head, tail; memset(dep, , sizeof(dep));
head = , tail = ;
que[tail++] = s;
dep[s] = ; while (head != tail)
{
int u = que[head++], v;
for (int i = hd[u]; ~i; i = nt[i])
if (!dep[v = to[i]] && fl[i])
dep[v] = dep[u] + , que[tail++] = v;
} return dep[t];
} inline int dfs(int u, int f)
{
if (u == t || !f)
return f; int used = , flow, v; for (int i = hd[u]; ~i; i = nt[i])
if (dep[v = to[i]] == dep[u] + && fl[i])
{
flow = dfs(v, min(f - used, fl[i])); used += flow;
fl[i] -= flow;
fl[i^] += flow; if (used == f)
return f;
} if (!used)
dep[u] = ; return used;
} inline int dinic(void)
{
int maxFlow = , newFlow; while (bfs())
while (newFlow = dfs(s, inf))
maxFlow += newFlow; return maxFlow;
} signed main(void)
{
n = get_i();
m = get_i(); memset(hd, -, sizeof(hd)); for (int i = ; i <= m; ++i)
{
int u = get_i();
int v = get_i();
int f = get_i();
add(u, v, f);
} s = , t = n - ; printf("%d\n", dinic());
}

Network Flow - Minimum Cost Flow

Time Limit : 1 sec, Memory Limit : 65536 KB

最小費用流

各辺にコストが設定されたフローネットワークにおいて、始点 ss から終点 tt まで流用 FF のフローを流すための最小コストを求めてください。

フローネットワークの各辺 ee には容量 c(e)c(e) 及びコスト d(e)d(e) が設定されています。各辺 ee には容量 c(e)c(e)を超えない流量 f(e)f(e) のフローを流すことができます。始点 ss から終点 tt へ流量 FF のフローを流したときの、∑e(f(e)×d(e))∑e(f(e)×d(e)) の最小値を求めてください。

入力

フローネットワーク G(V,E)G(V,E) が以下の形式で与えられる。

|V||E|F|V||E|F
u0v0c0d0u0v0c0d0
u1v1c1d1u1v1c1d1
:
u|E|1v|E|−1c|E|−1d|E|−1u|E|1v|E|−1c|E|−1d|E|−1

|V||V|, |E||E|, FF はそれぞれフローネットワーク GG の頂点の数、辺の数、流したい流量を示す。 GG の頂点にはそれぞれ 0,1,...,|V|−10,1,...,|V|−1 の*が付けられており、始点を 0、終点を |V|−1|V|−1 とする。

uiui, vivi, cici, didi はフローネットワーク GG の ii 番目の辺を表し、頂点 uiui から頂点 vivi に向かって容量が cici でコストが didi の辺があることを表す。

出力

最小費用流を1行に出力する。ただし、始点 ss から終点 tt へ流量 FF のフローを流すことができない場合は -1 を1行に出力する。

制約

  • 2 ≤ |V||V| ≤ 100
  • 1 ≤ |E||E| ≤ 1000
  • 0 ≤ FF ≤ 1000
  • 0 ≤ cici, didi ≤ 1000
  • uiui ≠≠ vivi
  • 頂点 xx から頂点 yy に向かって辺がある場合、頂点 yy から頂点 xx に向かう辺(逆辺)はない。

入力例

4 5 2
0 1 2 1
0 2 1 2
1 2 1 1
1 3 1 3
2 3 2 1

出力例

6
 #include <bits/stdc++.h>

 #define fread_siz 1024

 inline int get_c(void)
{
static char buf[fread_siz];
static char *head = buf + fread_siz;
static char *tail = buf + fread_siz; if (head == tail)
fread(head = buf, , fread_siz, stdin); return *head++;
} inline int get_i(void)
{
register int ret = ;
register int neg = false;
register int bit = get_c(); for (; bit < ; bit = get_c())
if (bit == '-')neg ^= true; for (; bit > ; bit = get_c())
ret = ret * + bit - ; return neg ? -ret : ret;
} template <class T>
inline T min(T a, T b)
{
return a < b ? a : b;
} const int inf = 2e9;
const int maxn = ; int n, m;
int s, t;
int flow; int edges;
int hd[maxn];
int nt[maxn];
int to[maxn];
int vl[maxn];
int fl[maxn]; inline void add(int u, int v, int f, int w)
{
nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; vl[edges] = +w; hd[u] = edges++;
nt[edges] = hd[v]; to[edges] = u; fl[edges] = ; vl[edges] = -w; hd[v] = edges++;
} int dis[maxn];
int pre[maxn]; inline bool spfa(void)
{
static int que[maxn];
static int inq[maxn];
static int head, tail; memset(dis, 0x3f, sizeof(dis));
head = , tail = ;
que[tail++] = s;
pre[s] = -;
inq[s] = ;
dis[s] = ; while (head != tail)
{
int u = que[head++], v; inq[u] = ; for (int i = hd[u]; ~i; i = nt[i])
if (dis[v = to[i]] > dis[u] + vl[i] && fl[i])
{
dis[v] = dis[u] + vl[i];
pre[v] = i ^ ;
if (!inq[v])
inq[v] = , que[tail++] = v;
}
} return dis[t] < 0x3f3f3f3f;
} inline int expend(void)
{
int newFlow = inf; for (int i = pre[t]; ~i; i = pre[to[i]])
newFlow = min(newFlow, fl[i ^ ]); for (int i = pre[t]; ~i; i = pre[to[i]])
fl[i] += newFlow, fl[i^] -= newFlow; return flow -= newFlow, newFlow * dis[t];
} inline int mcmf(void)
{
int ret = ; while (spfa())
ret += expend(); return flow ? - : ret;
} signed main(void)
{
n = get_i();
m = get_i(); flow = get_i(); memset(hd, -, sizeof(hd)); for (int i = ; i <= m; ++i)
{
int u = get_i();
int v = get_i();
int f = get_i();
int w = get_i();
add(u, v, f, w);
} s = n, t = n - ; add(s, , flow, ); printf("%d\n", mcmf());
}

@Author: YouSiki