B Help Bob
简单博弈。。
E The Exchange of Items
MinCostMaxFlow
const int N = 200;
const int INF = 1e9;
const double EPS = 1e-9;
const int V = N + 2;
const int MAXE = 5000;
struct Edge {
int cap, nxt, to, cost;
};
class minCostMaxFlow {
public:
Edge E[MAXE];
int edges, head[V], bak[V], bake[V], dis[V];
bool vis[V];
void init() {
edges = 0;
memset(head, -1, sizeof(head));
}
void add_edge(int u, int v, int w, int c) {
E[edges] = (Edge) {c, head[u], v, w};
E[edges + 1] = (Edge) {0, head[v], u, -w};
head[u] = edges;
head[v] = edges + 1;
edges += 2;
}
pair<int, int> sol(int source, int target) {
int answer = 0, max_flow = 0;
while (true) {
for (int i = 0; i <= target; ++i) {
vis[i] = 0, dis[i] = INF;
}
queue<int> q;
vis[source] = 1;
dis[source] = 0;
q.push(source);
memset(bak, -1, sizeof(bak));
memset(bake, -1, sizeof(bake));
while (!q.empty()) {
int u = q.front(); q.pop();
vis[u] = 0;
for (int i = head[u]; i != -1;) {
Edge &e = E[i];
int v = e.to;
if ( e.cap > 0 && dis[u] + e.cost < dis[v] ) {
dis[v] = dis[u] + e.cost;
bak[v] = u;
bake[v] = i;
if ( !vis[v] ) {
vis[v] = 1;
q.push(v);
}
}
i = e.nxt;
}
}
if ( bak[target] == -1 ) break;
int flow = INF;
for (int i = target; i != source; i = bak[i])
if ( flow > E[bake[i]].cap ) flow = E[bake[i]].cap;
//cout << "debug: " << flow << endl;
for (int i = target; i != source; i = bak[i]) {
//cout << "bak: " << i << endl;
E[bake[i]].cap -= flow;
E[bake[i]^1].cap += flow;
}
max_flow += flow;
answer += dis[target] * flow;
}
return make_pair(answer, max_flow);
}
};
int n, m, ai[N], bi[N];
minCostMaxFlow sol;
int main() {
#ifdef _LOCA_ENV_
freopen("input.in", "r", stdin);
#endif // _LOCA_ENV
while ( scanf("%d%d", &n, &m) != EOF ) {
rep(i, 0, n-1) scanf("%d%d", ai + i, bi + i);
int source = n, target = n + 1, tmp = 0, tot = 0;
sol.init();
rep(i, 0, n-1) {
sol.add_edge(source, i, 0, ai[i]);
sol.add_edge(i, target, 0, bi[i]);
tmp += ai[i];
tot += bi[i];
}
rep(i, 0, m-1) {
int u, v;
scanf("%d%d", &u, &v);
-- u, -- v;
sol.add_edge(u, v, 1, INF);
sol.add_edge(v, u, 1, INF);
}
if ( tmp != tot ) {
puts("-1");
continue;
}
pair<int, int> pi = sol.sol(source, target);
//cout << "min cost: " << pi.first << endl;
//cout << "max flow: " << pi.second << endl;
if (pi.second != tot) {
puts("-1");
} else {
printf("%d\n", pi.first);
}
}
return 0;
}
H Twelves Monkeys
画图可以发现, 我们只需要从后往前扫一遍, 同时维护可以回到的最小和次小值。用 multiset 即可。