Skip to content

Commit 2578f8d

Browse files
committed
refactor NetworkFlow, add a faster convolution
1 parent d31bc98 commit 2578f8d

File tree

2 files changed

+110
-64
lines changed

2 files changed

+110
-64
lines changed

graph-utility/NetworkFlow.cc

Lines changed: 74 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,79 +2,102 @@
22
#include <algorithm>
33

44
namespace NetFlow {
5-
const int N=100000,MAXM=100000,inf=1e9;
6-
struct Edge {
7-
int v,c,f,nx;//c:capcity, f:flow
8-
Edge() {}
9-
Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
10-
} E[MAXM];
11-
int G[N],cur[N],pre[N],dis[N],gap[N],n,sz;
5+
using flow_t = int;
6+
const int N = 1e5 + 10, M = 1e5 + 10;
7+
const flow_t inf = 1e9;
8+
struct edge_t {
9+
int to, nx;
10+
flow_t cap, flow;
11+
edge_t() {}
12+
edge_t(int to, int nx, flow_t cap):
13+
to(to), nx(nx), cap(cap), flow(0) {}
14+
} edges[M];
15+
int G[N], cur[N], pre[N], gap[N], n, sz;
16+
flow_t dis[N];
1217
void init(int _n) {
13-
n=_n,sz=0; memset(G,-1,sizeof(G[0])*n);
18+
n = _n, sz = 0;
19+
memset(G, -1, sizeof(*G) * n);
1420
}
15-
void link(int u,int v,int c) {
16-
E[sz]=Edge(v,c,0,G[u]); G[u]=sz++;
17-
E[sz]=Edge(u,0,0,G[v]); G[v]=sz++;
21+
void link(int u, int v, flow_t c) {
22+
edges[sz] = edge_t(v, G[u], c); G[u] = sz++;
23+
edges[sz] = edge_t(u, G[v], 0); G[v] = sz++;
1824
}
19-
int ISAP(int S,int T) {//S -> T
20-
int maxflow=0,aug=inf,flag=false,u,v;
21-
for (int i=0;i<n;++i)cur[i]=G[i],gap[i]=dis[i]=0;
22-
for (gap[S]=n,u=pre[S]=S;dis[S]<n;flag=false) {
23-
for (int &it=cur[u];~it;it=E[it].nx) {
24-
if (E[it].c>E[it].f&&dis[u]==dis[v=E[it].v]+1) {
25-
if (aug>E[it].c-E[it].f) aug=E[it].c-E[it].f;
26-
pre[v]=u,u=v; flag=true;
27-
if (u==T) {
28-
for (maxflow+=aug;u!=S;) {
29-
E[cur[u=pre[u]]].f+=aug;
30-
E[cur[u]^1].f-=aug;
25+
flow_t ISAP(int S, int T) {//S -> T
26+
flow_t maxflow = 0, aug = inf;
27+
memcpy(cur, G, sizeof(*G) * n);
28+
memset(gap, 0, sizeof(*gap) * n);
29+
memset(dis, 0, sizeof(*dis) * n);
30+
gap[S] = n, pre[S] = S;
31+
for (int u = S, flag = 0; dis[S] < n; flag = 0) {
32+
for (int &it = cur[u]; ~it; it = edges[it].nx) {
33+
int v = edges[it].to;
34+
if (edges[it].cap > edges[it].flow && dis[u] == dis[v] + 1) {
35+
aug = std::min(aug, edges[it].cap - edges[it].flow);
36+
pre[v] = u, u = v, flag = true;
37+
if (u == T) {
38+
for (maxflow += aug; u != S; ) {
39+
u = pre[u];
40+
edges[cur[u]].flow += aug;
41+
edges[cur[u] ^ 1].flow -= aug;
3142
}
32-
aug=inf;
43+
aug = inf;
3344
}
3445
break;
3546
}
3647
}
3748
if (flag) continue;
38-
int mx=n;
39-
for (int it=G[u];~it;it=E[it].nx) {
40-
if (E[it].c>E[it].f&&dis[E[it].v]<mx) {
41-
mx=dis[E[it].v]; cur[u]=it;
49+
int mx = n;
50+
for (int it = G[u]; ~it; it = edges[it].nx) {
51+
if (edges[it].cap > edges[it].flow && dis[edges[it].to] < mx) {
52+
mx = dis[edges[it].to];
53+
cur[u] = it;
4254
}
4355
}
44-
if ((--gap[dis[u]])==0) break;
45-
++gap[dis[u]=mx+1]; u=pre[u];
56+
if (--gap[dis[u]] == 0) break;
57+
++gap[dis[u] = mx + 1];
58+
u = pre[u];
4659
}
4760
return maxflow;
4861
}
49-
bool bfs(int S,int T) {
50-
static int Q[N]; memset(dis,-1,sizeof(dis[0])*n);
51-
dis[S]=0; Q[0]=S;
52-
for (int h=0,t=1,u,v,it;h<t;++h) {
53-
for (u=Q[h],it=G[u];~it;it=E[it].nx) {
54-
if (dis[v=E[it].v]==-1&&E[it].c>E[it].f) {
55-
dis[v]=dis[u]+1; Q[t++]=v;
62+
bool bfs(int S, int T) {
63+
static int Q[N];
64+
memset(dis, -1, sizeof(*dis) * n);
65+
dis[S] = 0, Q[0] = S;
66+
for (int h = 0, t = 1; h < t; ++h) {
67+
for (int u = Q[h], it = G[u]; ~it; it = edges[it].nx) {
68+
int v = edges[it].to;
69+
if (dis[v] == -1 && edges[it].cap > edges[it].flow) {
70+
dis[v] = dis[u] + 1;
71+
Q[t++] = v;
5672
}
5773
}
5874
}
59-
return dis[T]!=-1;
75+
return dis[T] != -1;
6076
}
61-
int dfs(int u,int T,int low) {
62-
if (u==T) return low;
63-
int ret=0,tmp,v;
64-
for (int &it=cur[u];~it&&ret<low;it=E[it].nx) {
65-
if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f) {
66-
if (tmp=dfs(v,T,std::min(low-ret,E[it].c-E[it].f))) {
67-
ret+=tmp; E[it].f+=tmp; E[it^1].f-=tmp;
77+
flow_t dfs(int u, int T, flow_t low) {
78+
if (u == T) return low;
79+
flow_t ret = 0;
80+
for (int &it = cur[u]; ~it && ret < low; it = edges[it].nx) {
81+
int v = edges[it].to;
82+
if (dis[v] == dis[u] + 1 && edges[it].cap > edges[it].flow) {
83+
flow_t tmp = dfs(v, T, std::min(low - ret, edges[it].cap - edges[it].flow));
84+
if (tmp > 0) {
85+
ret += tmp;
86+
edges[it].flow += tmp;
87+
edges[it ^ 1].flow -= tmp;
6888
}
6989
}
7090
}
71-
if (!ret) dis[u]=-1; return ret;
91+
if (!ret) dis[u] = -1;
92+
return ret;
7293
}
73-
int dinic(int S,int T) {
74-
int maxflow=0,tmp;
75-
while (bfs(S,T)) {
76-
memcpy(cur,G,sizeof(G[0])*n);
77-
while (tmp=dfs(S,T,inf)) maxflow+=tmp;
94+
flow_t dinic(int S, int T) {
95+
flow_t maxflow = 0, tmp;
96+
while (bfs(S, T)) {
97+
memcpy(cur, G, sizeof(*G) * n);
98+
while (tmp = dfs(S, T, inf)) {
99+
maxflow += tmp;
100+
}
78101
}
79102
return maxflow;
80103
}

mathematics/fast-fourier-transform.cc

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ namespace fft {
3535
const double pi = acos(-1.0);
3636
Complex w[N];
3737
int rev[N];
38-
void init(int n) {
39-
int LN = __builtin_ctz(n);
38+
void init(int L) {
39+
int n = 1 << L;
4040
for (int i = 0 ; i < n ; ++ i) {
4141
double ang = 2 * pi * i / n;
4242
w[i] = Complex(cos(ang) , sin(ang));
43-
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (LN - 1));
43+
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (L - 1));
4444
}
4545
}
4646
void trans(Complex P[], int n, int oper) {
@@ -68,9 +68,9 @@ namespace fft {
6868
}
6969
Complex A[N] , B[N] , C1[N] , C2[N];
7070
std::vector<int64> conv(const std::vector<int> &a, const std::vector<int> &b) {
71-
int n = a.size(), m = b.size(), s = 1;
72-
while (s <= n + m - 2) s <<= 1;
73-
init(s);
71+
int n = a.size(), m = b.size(), L = 0, s = 1;
72+
while (s <= n + m - 2) s <<= 1, ++L;
73+
init(L);
7474
for (int i = 0; i < s; ++i) {
7575
A[i] = i < n ? Complex(a[i], 0) : Complex();
7676
B[i] = i < m ? Complex(b[i], 0) : Complex();
@@ -90,17 +90,41 @@ namespace fft {
9090
}
9191
return res;
9292
}
93+
std::vector<int64> fast_conv(const std::vector<int> &a, const std::vector<int> &b) {
94+
int n = a.size(), m = b.size(), L = 0, s = 1;
95+
for (; s <= n + m - 2; s <<= 1, ++L);
96+
s >>= 1, --L;
97+
init(L);
98+
for (int i = 0; i < s; ++i) {
99+
A[i].x = (i << 1) < n ? a[i << 1] : 0;
100+
A[i].y = (i << 1 | 1) < n ? a[i << 1 | 1] : 0;
101+
B[i].x = (i << 1) < m ? b[i << 1] : 0;
102+
B[i].y = (i << 1 | 1) < m ? b[i << 1 | 1] : 0;
103+
}
104+
trans(A, s, 1); trans(B, s, 1);
105+
for (int i = 0; i < s; ++i) {
106+
int j = (s - i) & (s - 1);
107+
A[i] = (Complex(4, 0) * (A[j] * B[j]).conj() - (A[j].conj() - A[i]) * (B[j].conj() - B[i]) * (w[i] + Complex(1, 0))) * Complex(0, 0.25);
108+
}
109+
std::reverse(w + 1, w + s);
110+
trans(A, s, -1);
111+
std::vector<int64> res(n + m - 1);
112+
for (int i = 0; i <= (n + m - 1) / 2; ++i) {
113+
res[i << 1] = int64(A[i].y + 0.5);
114+
res[i << 1 | 1] = int64(A[i].x + 0.5);
115+
}
116+
return res;
117+
}
93118
// arbitrary modulo convolution
94119
void conv(int a[], int b[], int n, int m, int mod, int res[]) {
95-
int s = 1;
96-
while (s <= n + m - 2) s <<= 1;
97-
init(s);
120+
int s = 1, L = 0;
121+
while (s <= n + m - 2) s <<= 1, ++L;
122+
init(L);
98123
for (int i = 0; i < s; ++i) {
99124
A[i] = i < n ? Complex(a[i] / M, a[i] % M) : Complex();
100125
B[i] = i < m ? Complex(b[i] / M, b[i] % M) : Complex();
101126
}
102-
trans(A, s, 1);
103-
trans(B, s, 1);
127+
trans(A, s, 1); trans(B, s, 1);
104128
for (int i = 0; i < s; ++i) {
105129
int j = i ? s - i : i;
106130
Complex a1 = (A[i] + A[j].conj()) * Complex(0.5, 0);
@@ -112,8 +136,7 @@ namespace fft {
112136
C1[j] = c11 + c12 * Complex(0, 1);
113137
C2[j] = c21 + c22 * Complex(0, 1);
114138
}
115-
trans(C1, s, -1);
116-
trans(C2, s, -1);
139+
trans(C1, s, -1); trans(C2, s, -1);
117140
for (int i = 0 ; i < n + m - 1; ++i) {
118141
int x = int64(C1[i].x + 0.5) % mod;
119142
int y1 = int64(C1[i].y + 0.5) % mod;

0 commit comments

Comments
 (0)