Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using namespace std;
- #include <algorithm>
- #include <cctype>
- #include <cmath>
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <iostream>
- #include <limits>
- #include <map>
- #include <queue>
- #include <set>
- #include <sstream>
- #include <stack>
- #include <string>
- #include <vector>
- #define EPS 1e-11
- #define inf ( 1LL << 31 ) - 1
- #define LL long long
- #define _rep( i, a, b, x ) for( __typeof(b) i = ( a ); i <= ( b ); i += x )
- #define rep( i, n ) _rep( i, 0, n - 1, 1 )
- #define rrep( i, a, b ) for( __typeof(b) i = ( a ); i >= ( b ); --i )
- #define xrep( i, a, b ) _rep( i, a, b, 1 )
- #define abs(x) (((x)< 0) ? (-(x)) : (x))
- #define all(x) (x).begin(), (x).end()
- #define ms(x, a) memset((x), (a), sizeof(x))
- #define mp make_pair
- #define pb push_back
- #define sz(k) (int)(k).size()
- typedef vector <int> vi;
- // dinic algorithm
- /* notes
- source sink : 0 based
- no of edges will always be double of no of edges in the network
- change the value of data accoring to data type
- */
- struct dinic
- {
- int n, m, s, t, head, tail, ne;
- #define data int // change int -> LL if needed
- data data_inf;
- int *to, *next, *last, *d, *q, *now, *invalid, *cantuse;
- data *cap;
- dinic() {}
- dinic(int xn, int xm)
- {
- n = xn; m = xm; ne = 0;
- to = new int[m]; cap = new data[m]; next = new int[m];
- d = new int[n]; q = new int[n+n]; now = new int[n]; last = new int[n]; invalid = new int[n], cantuse = new int[m];
- fill(last, last+n, -1);
- fill(invalid, invalid+n, 0);
- fill(cantuse, cantuse+n, 0);
- }
- void clear() { ne = 0; fill(last, last+n, -1); }
- inline void add_edge(int u, int v, data uv, data vu)
- {
- to[ne] = v; cap[ne] = uv; next[ne] = last[u]; last[u] = ne++;
- to[ne] = u; cap[ne] = vu; next[ne] = last[v]; last[v] = ne++;
- }
- inline bool bfs()
- {
- fill(d, d+n, -1);
- head = tail = 0;
- d[t] = 0;
- q[tail++] = t;
- int u, v, e;
- while (head < tail)
- {
- u = q[head++];
- if (invalid[u]) continue;
- for (e = last[u]; e != -1; e = next[e])
- {
- if (cantuse[e]) continue;
- v = to[e];
- if (invalid[v]) continue;
- if (cap[e^1] > 0 && d[v] == -1)
- {
- q[tail++] = v;
- d[v] = d[u] + 1;
- }
- }
- }
- return d[s] != -1;
- }
- data dfs(int u, data f)
- {
- if (u == t) return f;
- int v;
- data ret;
- for (int &e = now[u]; e != -1; e = next[e])
- {
- if (cantuse[e]) continue;
- v = to[e];
- if (invalid[v]) continue;
- if (cap[e] > 0 && d[u] == d[v] + 1)
- {
- ret = dfs(v, min(f, cap[e]));
- if (ret > 0)
- {
- cap[e] -= ret;
- cap[e^1] += ret;
- return ret;
- }
- }
- }
- return 0;
- }
- data maxflow(int source, int sink, int N)
- {
- s = source; t = sink;
- data f = 0, x;
- data_inf = numeric_limits<data>::max();
- while (bfs())
- {
- rep(i,n) now[i] = last[i];
- while (true)
- {
- x = dfs(s, data_inf);
- if (x == 0) break;
- f = f + x;
- }
- }
- return f;
- }
- } G(150, 150*150);
- const int MAXN = 70;
- const int MAXM = 70;
- int spot[MAXM];
- int K[MAXN];
- int pref[MAXN][MAXN];
- int assign[MAXN];
- int used[MAXM];
- int main()
- {
- #ifdef Local
- freopen("/home/wasi/Desktop/input.txt", "r", stdin);
- #endif
- int t, n, m, tcase = 1;
- scanf("%d", &t);
- while (t--)
- {
- scanf("%d %d", &n, &m);
- rep(i,m) scanf("%d", &spot[i]);
- rep(i,n)
- {
- scanf("%d",&K[i]);
- rep(j,K[i])
- {
- scanf("%d", &pref[i][j]);
- pref[i][j]--;
- }
- }
- G.clear();
- int source = n+m, sink = n+m+1, BIG = G.data_inf;
- rep(i,n) G.add_edge(source, i, 1, 0);
- rep(i,n) rep(j,K[i])
- G.add_edge(i, pref[i][j]+n, 1, 0);
- rep(i,m) G.add_edge(i+n, sink, spot[i], 0);
- int F = G.maxflow(source, sink, n+m+2), NF;
- printf("Case #%d:\n%d applicant(s) can be hired.\n", tcase++, F);
- rep(i,n) assign[i] = -1;
- rep(i,n)
- {
- rep(j,K[i])
- {
- int job = pref[i][j];
- if (spot[job] == 0) continue;
- spot[job]--;
- G.clear();
- rep(x,n) if (assign[x] == -1 && x != i) G.add_edge(source, x, 1, 0);
- rep(x,n) rep(y,K[x])
- {
- if (assign[x] != -1) continue;
- if (x == i) continue;
- G.add_edge(x, pref[x][y]+n, 1, 0);
- }
- rep(x,m) if (spot[x] > 0) G.add_edge(x+n, sink, spot[x], 0);
- NF = G.maxflow(source, sink, n+m+2);
- if (NF+1 == F)
- {
- assign[i] = job;
- printf("%d %d\n", i+1, job+1);
- F = NF;
- goto done;
- }
- spot[job]++;
- }
- done:;
- }
- }
- return 0;
- }
Add Comment
Please, Sign In to add comment