模型很明显, 但要注意输出解的方式, 需要先找出割边, 确定最小点权覆盖然后再求补集。
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <ctime>
#include <algorithm>
using namespace std;
const int N = 205;
const int M = N * N * 2;
typedef int LL;
const LL INF = 1000000000;
struct Dinic {
struct Edge {
int v;
LL cap, flow;
Edge* next, * pair;
void init(int a, LL b, Edge* e1, Edge* e2) {
v = a, cap = b, flow = 0, next = e1, pair = e2;
}
};
Edge* head[N], * used[N];
Edge* it;
int lev[N], que[N];
Edge E[M];
int n, s, t;
LL maxFlow;
bool flag[N];
vector<int> v1, v2;
void init(int n, int s, int t) {
it = E;
this->n = n;
this->s = s, this->t = t;
for (int i = 0; i < n; i++)
head[i] = 0;
}
void add(int u, int v, LL c) {
it->init(v, c, head[u], it + 1);
head[u] = it++;
it->init(u, 0, head[v], it - 1);
head[v] = it++;
}
bool bfs() {
for (int i = 0; i < n; lev[i++] = -1);
lev[s] = 1;
int st = 0, ed = 0;
que[ed++] = s;
while (st < ed) {
int u = que[st++];
for (Edge* e = head[u]; e; e = e->next) {
int v = e->v;
if (lev[v] == -1 && e->cap > e->flow) {
lev[v] = lev[u] + 1;
que[ed++] = v;
}
}
}
return lev[t] != -1;
}
LL dfs(int u, LL f) {
if (u == t) return f;
for (Edge* & e = used[u]; e; e = e->next) {
int v = e->v;
if (e->cap > e->flow && lev[v] == lev[u] + 1) {
LL tmp = dfs(v, min(e->cap - e->flow, f));
if (tmp > 0) {
e->flow += tmp;
e->pair->flow -= tmp;
return tmp;
}
}
}
return 0;
}
void run() {
maxFlow = 0;
while (bfs()) {
for (int i = 0; i < n; i++)
used[i] = head[i];
LL f = 1;
while (f) {
f = dfs(s, INF);
maxFlow += f;
}
}
}
void gao(int a) {
fill(flag, flag + n, 0);
for (int u = 0; u < n; u++) {
for (Edge* e = head[u]; e; e = e->next) {
int v = e->v;
if (lev[v] * lev[u] < 0) {
flag[u] = 1, flag[v] = 1;
}
}
}
v1.clear(), v2.clear();
for (int i = 1; i <= a; i++)
if (!flag[i]) {
v1.push_back(i);
}
for (int i = a + 1; i < n - 1; i++)
if (!flag[i]) {
v2.push_back(i);
}
printf(" %d %d\n", v1.size(), v2.size());
for (int i = 0; i < v1.size(); i++)
printf("%d ", v1[i]);
puts("");
sort(v2.begin(), v2.end());
for (int i = 0; i < v2.size(); i++)
printf("%d ", v2[i] - a);
puts("");
}
}G;
int main() {
int m, a, b, n, s, u, v, t, sum;
while (~scanf("%d%d%d", &a, &b, &m)) {
n = a + b + 2;
G.init(n, 0, n - 1);
sum = 0;
for (int i = 1; i <= a; i++) {
scanf("%d", &t);
G.add(0, i, t);
sum += t;
}
for (int i = 1; i <= b; i++) {
scanf("%d", &t);
G.add(a + i, n - 1, t);
sum += t;
}
for (int i = 0; i < m; i++) {
scanf("%d%d", &u, &v);
G.add(u, v + a, INF);
}
G.run();
printf("%d", sum - G.maxFlow);
G.gao(a);
}
return 0;
}