Pagini recente » Cod sursa (job #453144) | Cod sursa (job #1926030) | Cod sursa (job #1177730) | Cod sursa (job #2124314) | Cod sursa (job #1110339)
//Problem algola from Infoarena
#include <cmath>
#include <cstdint>
#include <cassert>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <queue>
#include <vector>
using namespace std;
ifstream fin("algola.in");
ofstream fout("algola.out");
const int8_t INF = 1 << 7;
const int MAX_K = 55;
const int MAX_N = 5005;
int N, M, K;
vector<pair<int, int>> edges[MAX_K];
vector<int> graph[MAX_N];
int8_t cap[MAX_N][MAX_N];
int8_t flow[MAX_N][MAX_N];
int source, sink;
void read_input();
void solve();
int maxflow();
bool find_augmenting_path(int father[]);
void add_edge(int a, int b, int c);
int hash_node(int n, int c);
void add_flow(int a, int b, int f);
int cp(int a, int b);
int main() {
read_input();
solve();
return 0;
}
void read_input() {
fin >> N >> M;
source = 1;
for (int i = 1, x; i <= N; i += 1) {
fin >> x;
K += x;
add_edge(source, hash_node(i, 1), x);
}
for (int i = 1, a, b, c; i <= M; i += 1) {
fin >> a >> b >> c;
edges[a].push_back(make_pair(b, c));
edges[b].push_back(make_pair(a, c));
}
}
void solve() {
int cost = 1;
sink = hash_node(1, cost);
while (maxflow() < K) {
for (int i = 1; i <= N; i += 1) {
int node = hash_node(i, cost);
int higher = hash_node(i, cost + 1);
add_edge(node, higher, INF);
for (auto x: edges[i]) {
add_edge(node, hash_node(x.first, cost + 1), x.second);
}
}
cost += 1;
sink = hash_node(1, cost);
}
fout << cost - 2;
}
inline void add_edge(int a, int b, int c) {
assert(a < MAX_N && b < MAX_N);
graph[a].push_back(b);
graph[b].push_back(a);
cap[a][b] = c;
}
inline int hash_node(int n, int c) {
return (c * MAX_K + n);
}
int maxflow() {
static int result = 0;
int father[MAX_N];
while (find_augmenting_path(father)) {
for (auto x: graph[sink]) {
if (father[x] == 0 || cp(x, sink) == 0) continue;
int new_flow = cp(x, sink);
for (int node = x; node != source; node = father[node]) {
new_flow = min(new_flow, cp(father[node], node));
}
add_flow(x, sink, new_flow);
for (int node = x; node != source; node = father[node]) {
add_flow(father[node], node, new_flow);
}
result += new_flow;
}
}
return result;
}
bool find_augmenting_path(int father[]) {
fill(father, father + MAX_N, 0);
father[source] = source;
queue<int> q;
q.push(source);
while (!q.empty()) {
int node = q.front();
q.pop();
if (node == sink) return true;
for (auto next: graph[node]) {
if (father[next] == 0 && cp(node, next) > 0) {
father[next] = node;
q.push(next);
}
}
}
return false;
}
inline void add_flow(int a, int b, int f) {
flow[a][b] += f;
flow[b][a] -= f;
}
inline int cp(int a, int b) {
return cap[a][b] - flow[a][b];
}