思路
最大流。建一个超级源点和超级汇点,然后从源点连出两条边,流量分别为a和b,最后将这两个定点分别向汇点连一条流量为无穷大的边,求得的最大流即为答案。
代码
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#define BLA(X) int X[100001] = { 0 }
BLA(HEAD);
BLA(NEX);
BLA(PRE);
BLA(V);
BLA(USED);
bool VIS[100001] = { 0 };
BLA(LIS);
int S, T;
int tot = 0;
void INS(const int x, const int y, const int v)
{
tot++;
LIS[tot] = y;
NEX[tot] = HEAD[x];
HEAD[x] = tot;
V[tot] = v;
}
void INSERT(const int x, const int y, const int v)
{
INS(x, y, v);
INS(y, x, 0);
}
bool bfs(const int S)
{
std::queue<int> q;
q.push(S);
std::memset(PRE, 0xff, sizeof PRE);
PRE[S] = 1;
while (!q.empty())
{
int x = q.front();
q.pop();
for (int t = HEAD[x]; t; t = NEX[t])
if (PRE[LIS[t]] == -1 && V[t])
{
PRE[LIS[t]] = PRE[x] + 1;
q.push(LIS[t]);
}
}
if (PRE[T] == -1)
return false;
return true;
}
int dfs(const int pos, const int flow)
{
if (pos == T)
return flow;
int w, t, used = 0;
for (int t = HEAD[pos]; t; t = NEX[t])
{
if (V[t] && PRE[LIS[t]] == PRE[pos] + 1)
{
w = dfs(LIS[t], std::min(flow - used, V[t]));
used += w;
V[t] -= w;
V[t + 1] += w;
if (used == flow)
return flow;
}
}
if (!used)
PRE[pos] = -1;
return used;
}
int DINIC(const int S)
{
int ans = 0;
while (bfs(S))
ans += dfs(S, INT_MAX);
return ans;
}
int main(int argc, char **argv)
{
int x, y;
std::cin >> x >> y;
INSERT(1, 2, x);
INSERT(1, 3, y);
INSERT(2, 4, x);
INSERT(3, 4, y);
S = 1;
T = 4;
std::cout << DINIC(1) << std::endl;
#ifdef __EDWARD_EDIT
std::cin.get();
std::cin.get();
#endif
return 0;
}