-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPrimalDual.cpp
More file actions
81 lines (76 loc) · 1.59 KB
/
PrimalDual.cpp
File metadata and controls
81 lines (76 loc) · 1.59 KB
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
//O(FElogV)
using Flow=int;
using Cost=int;
struct Edge{
int to, rev;
Flow cap;
Cost cost;
};
using Edges=vector<Edge>;
using Graph=vector<Edges>;
class MinCostFlow
{
public:
vector<vector<Edge>> g;
MinCostFlow(const int n):g(vector<vector<Edge>>(n))
{}
const void add_Edge(const int from, const int to, const Flow cap, const Cost cost)
{
g[from].push_back((Edge){to, (int)g[to].size(), cap, cost});
g[to].push_back((Edge){from, (int)g[from].size()-1, 0, -cost});
}
const Cost primal_dual(const int s, const int t, Flow f);
private:
const Cost INF=1e9;
};
const Cost MinCostFlow::primal_dual(const int s, const int t, Flow f)
{
int n=g.size();
vector<Cost> h(n), dist(n);
vector<int> prevv(n), preve(n);
using P=pair<Cost, int>;
Cost res=0;
fill(ALL(h), 0);
while(f>0)
{
priority_queue<P, vector<P>, greater<P>> que;
fill(ALL(dist), INF);
dist[s]=0;
que.push(P(0, s));
while(!que.empty())
{
P p=que.top();
que.pop();
int v=p.second;
if(dist[v] < p.first) continue;
for(int i=0;i<g[v].size();i++)
{
Edge &e=g[v][i];
if(e.cap>0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to])
{
dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
prevv[e.to] = v;
preve[e.to] = i;
que.push(P(dist[e.to], e.to));
}
}
}
if(dist[t]==INF)
return -1;
for(int v=0;v<n;v++) h[v] += dist[v];
Flow d=f;
for(int v=t;v!=s;v=prevv[v])
{
d=min(d, g[prevv[v]][preve[v]].cap);
}
f-=d;
res+=d*h[t];
for(int v=t;v!=s;v=prevv[v])
{
Edge &e=g[prevv[v]][preve[v]];
e.cap-=d;
g[v][e.rev].cap+=d;
}
}
return res;
}