https://www.luogu.org/problem/P2763
题意:很简单,都是中文,给出每种类型试题的数量,同时,给出每道题,可以充当的试题种类。
做法:设一个源点,与每一个试题类型建边,容量为试题的数量,同时每种试题类型在对每一个题型建立一条边,容量为1,最后在连接汇点。跑一个最大流即可。
#include "bits/stdc++.h"
using namespace std;
inline int read() {
int x = 0;
bool f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = 0;
for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
if (f) return x;
return 0 - x;
}
const int inf = 0x3f3f3f3f;
const int maxn = 100000 + 10;
int head[maxn], dis[maxn], cnt;
struct node {
int val, v, nxt;
} e[maxn << 1];
void init() {
cnt = 0;
memset(head, -1, sizeof(head));
}
void add_edge(int u, int v, int val) {
e[cnt].v = v;
e[cnt].val = val;
e[cnt].nxt = head[u];
head[u] = cnt++;
}
int bfs(int s, int t) {
queue<int> qu;
memset(dis, -1, sizeof(dis));
dis[s] = 0;
qu.push(s);
while (!qu.empty()) {
int x = qu.front();
qu.pop();
for (int i = head[x]; i != -1; i = e[i].nxt) {
int now = e[i].v;
if (dis[now] == -1 && e[i].val != 0) {
dis[now] = dis[x] + 1;
qu.push(now);
}
}
}
return dis[t] != -1;
}
int dfs(int x, int t, int maxflow) {
if (x == t) return maxflow;
int ans = 0;
for (int i = head[x]; i != -1; i = e[i].nxt) {
int now = e[i].v;
if (dis[now] != dis[x] + 1 || e[i].val == 0 || ans >= maxflow)
continue;
int f = dfs(now, t, min(e[i].val, maxflow - ans));
e[i].val -= f;
e[i ^ 1].val += f;
ans += f;
}
return ans;
}
int Dinic(int s, int t) {
int ans = 0;
while (bfs(s, t)) {
ans += dfs(s, t, inf);
}
return ans;
}
set<int> se[maxn];
int a[maxn];
int main() {
init();
int k, n, ss, tt, x, cc, sum = 0;
scanf("%d%d", &k, &n);
ss = 0;
for (int i = 1; i <= k; i++) {
scanf("%d", &x);
sum += x;
add_edge(ss, i, x);
add_edge(i, ss, 0);
}
tt = n + k + 1;
for (int i = 1; i <= n; i++) {
scanf("%d", &cc);
while (cc--) {
scanf("%d", &x);
add_edge(x, i + k, 1);
add_edge(i + k, x, 0);
}
add_edge(i + k, tt, 1);
add_edge(tt, i + k, 0);
}
int ans = Dinic(ss, tt);
if (ans != sum) {
printf("No Solution!\n");
} else {
for (int i = 0; i < cnt; i += 2) {
if (e[i].v != ss && e[i ^ 1].v != ss)
if (e[i].v != tt && e[i ^ 1].v != tt)
if (e[i ^ 1].val != 0) {
se[e[i ^ 1].v].insert(e[i].v - k);
}
}
for (int i = 1; i <= k; i++) {
printf("%d:", i);
for (auto it = se[i].begin(); it != se[i].end(); it++) {
printf(" %d", *it);
}
cout << endl;
}
}
return 0;
}