-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathE.cpp
126 lines (98 loc) · 3.12 KB
/
E.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <iostream>
#include <climits>
#include <vector>
#include <deque>
size_t n, m;
const long long INF = LONG_LONG_MAX;
struct Edge {
int from, to;
long long flow, cap, cost;
int reversed = -1;
Edge(int from, int to, long long int f, long long int cap, long long int cost) : from(from), to(to), flow(f),
cap(cap),
cost(cost) {}
};
int nullSource, nullSink;
std::vector<std::vector<Edge>> edges;
std::vector<long long> d;
std::vector<int> id;
std::vector<Edge*> p;
void addEdge(int from, int to, long long flow, long long cap, long long cost) {
Edge edge = Edge(from, to, flow, cap, cost);
Edge rev = Edge(to, from, flow, 0, -cost);
edges[from].push_back(edge);
edges[to].push_back(rev);
edges[from].back().reversed = edges[to].size() - 1;
edges[to].back().reversed = edges[from].size() - 1;
}
long long levitAlgorithm() {
long long minCost = 0;
long long maxFlow = 0;
while (true) {
std::deque<int> q;
id.assign(n + 1, 0);
d.assign(n + 1, INF);
p.resize(n + 1);
d[0] = 0;
q.push_back(0);
while (!q.empty()) {
int u = q.front();
q.pop_front();
id[u] = 2;
for (Edge& edge : edges[u]) {
if (edge.flow < edge.cap && d[edge.to] > d[edge.from] + edge.cost) {
d[edge.to] = d[edge.from] + edge.cost;
if (!id[edge.to]) {
q.push_back(edge.to);
} else if (id[edge.to] == 2) {
q.push_front(edge.to);
}
id[edge.to] = 1;
p[edge.to] = &edge;
}
}
}
long long del = INF;
if (d[nullSink] == INF) {
break;
} else {
for (int u = nullSink; u != nullSource; u = p[u]->from) {
Edge* edge = p[u];
del = std::min(del, edge->cap - edge->flow);
}
for (int u = nullSink; u != nullSource; u = p[u]->from) {
Edge* edge = p[u];
Edge* reversed = &edges[edge->to][edge->reversed];
edge->flow += del;
reversed->flow -= del;
minCost += del * edge->cost;
}
maxFlow += del;
}
}
return minCost;
}
int main() {
std::cin >> n >> m;
std::vector<long long> a(n + 1);
size_t nn = 2 * n + 1;
edges.assign(nn + 1, std::vector<Edge>());
for (int i = 1; i <= n; ++i) {
std::cin >> a[i];
addEdge(n + i, i, 0, INF, a[i]);
addEdge(0, n + i, 0, 1, 0);
addEdge(i, nn, 0, 1, 0);
addEdge(i, n + i, 0, INF, 0);
}
for (int i = 0; i < m; ++i) {
int u, v;
long long cost;
std::cin >> u >> v >> cost;
addEdge(n + u, v, 0, INF, cost);
}
nullSource = 0;
nullSink = nn;
n = nn + 1;
std::cout << levitAlgorithm() << "\n";
return 0;
}