思路:
构图后使用dinic算法,如果最大流等于sum(m[i])(i = 1, 2, 3, ..., M),则可以,否则不行。
实现:
1 #include <bits/stdc++.h> 2 3 #define N (205) 4 #define M (N * N + 4 * N) 5 const int INF = 0x3f3f3f3f; 6 typedef long long LL; 7 8 using namespace std; 9 10 struct edge 11 { 12 int v, cap, next; 13 }; 14 edge e[M]; 15 16 int head[N], level[N], cur[N]; 17 int num_of_edges; 18 19 void dinic_init(void) 20 { 21 num_of_edges = 0; 22 memset(head, -1, sizeof(head)); 23 return; 24 } 25 26 int add_edge(int u, int v, int c1, int c2) 27 { 28 int& i = num_of_edges; 29 30 assert(c1 >= 0 && c2 >= 0 && c1 + c2 >= 0); // check for possibility of overflow 31 e[i].v = v; 32 e[i].cap = c1; 33 e[i].next = head[u]; 34 head[u] = i++; 35 36 e[i].v = u; 37 e[i].cap = c2; 38 e[i].next = head[v]; 39 head[v] = i++; 40 return i; 41 } 42 43 int dfs(int u, int t, int bn) 44 { 45 if (u == t) return bn; 46 int left = bn; 47 for (int &i = cur[u]; i >= 0; i = e[i].next) 48 { 49 int v = e[i].v; 50 int c = e[i].cap; 51 if (c > 0 && level[u] + 1 == level[v]) 52 { 53 int flow = dfs(v, t, min(left, c)); 54 if (flow > 0) 55 { 56 e[i].cap -= flow; 57 e[i ^ 1].cap += flow; 58 cur[u] = i; 59 left -= flow; 60 if (!left) break; 61 } 62 } 63 } 64 if (left > 0) level[u] = 0; 65 return bn - left; 66 } 67 68 bool bfs(int s, int t) 69 { 70 memset(level, 0, sizeof(level)); 71 level[s] = 1; 72 queue<int> q; 73 q.push(s); 74 while (!q.empty()) 75 { 76 int u = q.front(); 77 q.pop(); 78 if (u == t) return true; 79 for (int i = head[u]; i >= 0; i = e[i].next) 80 { 81 int v = e[i].v; 82 if (!level[v] && e[i].cap > 0) 83 { 84 level[v] = level[u] + 1; 85 q.push(v); 86 } 87 } 88 } 89 return false; 90 } 91 92 LL dinic(int s, int t) 93 { 94 LL max_flow = 0; 95 96 while (bfs(s, t)) 97 { 98 memcpy(cur, head, sizeof(head)); 99 max_flow += dfs(s, t, INT_MAX); 100 } 101 return max_flow; 102 } 103 104 int main() 105 { 106 int T, n, m; 107 cin >> T; 108 while (T--) 109 { 110 dinic_init(); 111 int x, y, sum = 0; 112 cin >> n >> m; 113 for (int i = 1; i <= m; i++) 114 { 115 cin >> x; 116 sum += x; 117 add_edge(n + i, n + m + 1, x, 0); 118 } 119 for (int i = 1; i <= n; i++) 120 { 121 cin >> x; 122 add_edge(0, i, x, 0); 123 cin >> y; 124 while (y--) 125 { 126 cin >> x; 127 add_edge(i, n + x, 1, 0); 128 } 129 } 130 if (dinic(0, n + m + 1) == sum) cout << "Yes" << endl; 131 else cout << "No" << endl; 132 } 133 return 0; 134 }