/* Tag 网络流算法 0点作为起始点,1-MAX_M作为所有movie点,(MAX_M + 1) - (MAX_M + MAX_D)作为日期点,(MAX_M + MAX_D + 1)作为终点建图 0点和movie i之间的权值为i对应的D值 movie i 和 所有i可取的日期之间的权值为1 所有日期和终点之间的权值为1 */ #include <iostream> #define MAX_M 20 #define MAX_D 380 using namespace std; int temp[8]; int n, total; int gf[MAX_D][MAX_D], f[MAX_D][MAX_D]; int pre[MAX_D]; int bfsq[MAX_D + 5], head, tail; bool v[MAX_D]; int minV; //插入权值为w的边[from, to] void insertEdge(int from, int to, int w) { gf[from][to] = w; } //初始化,建图 void init() { total = 0; memset(gf, 0, sizeof(gf)); memset(f, 0, sizeof(f)); int i, j, k, D, W; scanf("%d", &n); for(i = 1; i <= n; i++) { for(j = 1; j <= 7; j++) scanf("%d", &temp[j]); scanf("%d%d", &D, &W); insertEdge(0, i, D); total += D; for(j = 1; j <= 7; j++) { if(temp[j] == 0) continue; for(k = 1; k <= W; k++) { int to = 20 + (k - 1) * 7 + j; insertEdge(i, to, 1); insertEdge(to, 371, 1); } } } } //bfs寻找增广矩阵 bool bfs() { for(int i = 0; i <= 371; i++) { v[i] = false; pre[i] = -1; } v[0] = true; head = tail = 1; bfsq[tail] = 0; tail = tail % MAX_D + 1; while(head != tail) { int from = bfsq[head]; head = head % MAX_D + 1; if(from == 371) { int a = 2; break; } for(int to = 0; to <= 371; to++) { if(!v[to] && gf[from][to] > 0) { v[to] = true; pre[to] = from; bfsq[tail] = to; tail = tail % MAX_D + 1; } } } //寻找路径中的最小权值边 minV = INT_MAX; int to = 371, from; if(pre[to] == -1) return false; else{ while((from = pre[to])!= -1) { if(gf[from][to] < minV) minV = gf[from][to]; to = from; } } return true; } //网络流的edmonds karp算法 void edmondsKarp() { //不断寻找增广路径 while(bfs()) { int to = 371, from; while((from = pre[to]) != -1) { gf[from][to] = gf[from][to] - minV; gf[to][from] = gf[to][from] + minV; f[from][to] = f[from][to] + minV; f[to][from] = -f[from][to]; to = from; } } } int main() { int caseNum; scanf("%d", &caseNum); while(caseNum--) { init(); edmondsKarp(); int countv = 0; for(int i = 1; i <= n; i++) countv += f[0][i]; if(countv == total) printf("Yes/n"); else printf("No/n"); } return 0; }