-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathMinCostFlow.cpp
93 lines (81 loc) · 1.55 KB
/
MinCostFlow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
Proof : Min Cost Flow
Interface is :
Call init function and then just use addEdge to fill in all edges
After that just call minCost function. Taddda!
Orders :
Time -> O(F*E*V)
Space -> O(V*V)
*/
int T;
VVI adjList;
VVI cost,cap;
VI deg;
void initFlow(int _T)
{
T= _T;
cost.resize(T);
cap.resize(T);
for(int i=0;i<T;i++)
{
cost[i].resize(T);
cap[i].resize(T);
}
deg.resize(T);
adjList.resize(T);
}
void addEdge(int a, int b, int cap1, int cap2, int cost1, int cost2)
{
adjList[a].pb(b); adjList[b].pb(a);
cap[a][b]=cap1; cap[b][a]=cap2;
cost[a][b]=cost1; cost[b][a]=cost2;
}
// Returns cost of sending need flow, -INF if its impossible
int minCostFlow(int src, int dest, int need)
{
int C=0;
VI dist(T);
VI parent(T);
VI done(T);
while( need > 0)
{
for(int i=0;i<T;i++)
{
dist[i]=INF;
parent[i]=-1;
done[i]=false;
}
dist[src] = 0;
while(true)
{
bool changed = false;
for(int i = 0; i < T; i++)
{
if(done[i] || dist[i]>=INF) continue;
done[i]=true;
for(int j = 0; j < adjList[i].size(); j++)
{
int v = adjList[i][j];
if( dist[v] > dist[i] + cost[i][v] && cap[i][v] > 0)
{
dist[v] = dist[i] + cost[i][v];
parent[v] = i; done[v]=false;
changed = true;
}
}
}
if (!changed) break;
}
if( dist[dest] == INF) break;
C += dist[dest];
need--;
for(int cur = dest; cur != src; cur = parent[cur])
{
int v = parent[cur];
cap[v][cur] --;
cap[cur][v] ++;
}
}
if( need > 0) return -INF;
return C;
}