Skip to content

Instantly share code, notes, and snippets.

@yurahuna
Last active September 20, 2016 12:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yurahuna/f67538cbde0aea1e9094b39a3c7e317f to your computer and use it in GitHub Desktop.
Save yurahuna/f67538cbde0aea1e9094b39a3c7e317f to your computer and use it in GitHub Desktop.
struct edge { int to, cap, rev; };
using Graph = vector<vector<edge>>;
const int inf = 1e9;
const int MAX_V = 110;
int level[MAX_V];
int iter[MAX_V];
bool reachable[MAX_V]; // 残余グラフにおいて、Sから到達可能か
void add_edge(Graph& G, int from, int to, int cap) {
G[from].emplace_back((edge){to, cap, (int)G[to].size()});
G[to].emplace_back((edge){from, 0, (int)G[from].size() - 1});
}
void bfs(Graph& G, int s) {
memset(level, -1, sizeof(level));
queue<int> que;
level[s] = 0;
que.push(s);
while (!que.empty()) {
int v = que.front(); que.pop();
for (int i = 0; i < G[v].size(); i++) {
edge &e = G[v][i];
if (e.cap > 0 && level[e.to] < 0) {
level[e.to] = level[v] + 1;
que.push(e.to);
}
}
}
}
int dfs(Graph& G, int v, int t, int f) {
if (v == t) return f;
for (int &i = iter[v]; i < G[v].size(); i++) {
edge &e = G[v][i];
if (e.cap > 0 && level[v] < level[e.to]) {
int d = dfs(G, e.to, t, min(f, e.cap));
if (d > 0) {
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
int max_flow(Graph& G, int s, int t) {
int flow = 0;
for (;;) {
bfs(G, s);
if (level[t] < 0) return flow;
memset(iter, 0, sizeof(iter));
int f;
while ((f = dfs(G, s, t, inf)) > 0) {
flow += f;
}
}
}
void my_dfs (Graph& G, int v) {
if (reachable[v]) return; // 既に来ていた
reachable[v] = true;
for (auto e : G[v]) {
if (e.cap > 0) {
my_dfs(G, e.to);
}
}
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int K, N, M;
cin >> K >> N >> M;
Graph G_ori(MAX_V);
const int s = K + N + 1, t = 0;
const int V = s + 1;
rep(i, M) {
int a, b, c;
cin >> a >> b >> c;
add_edge(G_ori, a, b, c);
add_edge(G_ori, b, a, c);
}
rep(i, K) {
add_edge(G_ori, s, i + 1, inf);
}
Graph G_flow = G_ori;
int flow = max_flow(G_flow, s, t);
my_dfs(G_flow, s);
vector<int> f1(V), f2(V); // s->i, i->t
f1[s] = inf; f2[t] = inf;
rep2(i, 1, K + N + 1) {
Graph G_tmp = G_flow;
if (reachable[i]) {
f1[i] = max_flow(G_tmp, s, i);
} else {
f2[i] = max_flow(G_tmp, i, t);
}
}
int ans = -1;
rep(v, V) {
for (auto e : G_ori[v]) {
int u = e.to;
if (reachable[v] && !reachable[u]) {
ans = max(ans, flow + min(f1[v], f2[u]));
}
}
}
if (ans >= inf) {
cout << "overfuro" << endl;
} else {
cout << ans << endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment