网络流解法:
容易想到将每一天看做一个点并和汇点连容量为1的边(因为一天只能做一件事情),每个电影看做一个点并和源点连容量为d的边(即几天可以完成),然后电影和对应天数连容量为1的边,求最大流判断是否满流即可。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int INF = 9999999; 7 const int N = 400; 8 const int M = 20000; 9 int head[N]; 10 int level[N]; 11 int q[N]; 12 int n, e, front, rear; 13 14 void init() 15 { 16 e = 0; 17 memset( head, -1, sizeof(head) ); 18 } 19 20 struct Edge 21 { 22 int v, next, cap; 23 } edge[M]; 24 25 void addEdge( int u, int v, int cap ) 26 { 27 edge[e].v = v; 28 edge[e].cap = cap; 29 edge[e].next = head[u]; 30 head[u] = e++; 31 edge[e].v = u; 32 edge[e].cap = 0; 33 edge[e].next = head[v]; 34 head[v] = e++; 35 } 36 37 bool bfs( int s, int t ) 38 { 39 front = rear = 0; 40 memset( level, -1, sizeof(level) ); 41 q[rear++] = s; 42 level[s] = 0; 43 while ( front < rear ) 44 { 45 int u = q[front++]; 46 for ( int i = head[u]; i != -1; i = edge[i].next ) 47 { 48 int v = edge[i].v, cap = edge[i].cap; 49 if ( level[v] == -1 && cap > 0 ) 50 { 51 level[v] = level[u] + 1; 52 q[rear++] = v; 53 } 54 } 55 } 56 return level[t] != -1; 57 } 58 59 int dfs( int u, int sum, int t ) 60 { 61 if ( u == t ) return sum; 62 int os = 0; 63 for ( int i = head[u]; i != -1; i = edge[i].next ) 64 { 65 int v = edge[i].v, cap = edge[i].cap; 66 if ( level[v] == level[u] + 1 && cap > 0 ) 67 { 68 int tt = dfs( v, min( sum, cap ), t ); 69 if ( tt == 0 ) continue; 70 edge[i].cap -= tt; 71 edge[i ^ 1].cap += tt; 72 sum -= tt; 73 os += tt; 74 if ( sum == 0 ) break; 75 } 76 } 77 if ( os == 0 ) level[u] = -1; 78 return os; 79 } 80 81 int dinic( int s, int t ) 82 { 83 int res = 0; 84 while ( bfs( s, t ) ) 85 { 86 res += dfs( s, INF, t ); 87 } 88 return res; 89 } 90 91 const int D = 7; 92 int nn[D]; 93 94 int main () 95 { 96 int _case; 97 scanf("%d", &_case); 98 while ( _case-- ) 99 { 100 scanf("%d", &n); 101 init(); 102 int tot = 0, wmax = -1, d, w; 103 for ( int i = 1; i <= n; i++ ) 104 { 105 for ( int j = 0; j < D; j++ ) 106 { 107 scanf("%d", nn + j); 108 } 109 scanf("%d%d", &d, &w); 110 tot += d; 111 wmax = max( wmax, w ); 112 addEdge( 0, i, d ); 113 for ( int j = 0; j < D; j++ ) 114 { 115 if ( nn[j] == 1 ) 116 { 117 for ( int k = 0; k < w; k++ ) 118 { 119 int num = n + k * 7 + j + 1; 120 addEdge( i, num, 1 ); 121 } 122 } 123 } 124 } 125 int tid = n + wmax * 7 + 1; 126 for ( int i = n + 1; i < tid; i++ ) 127 { 128 addEdge( i, tid, 1 ); 129 } 130 if ( dinic( 0, tid ) == tot ) 131 { 132 puts("Yes"); 133 } 134 else 135 { 136 puts("No"); 137 } 138 } 139 return 0; 140 }
匈牙利解法(些许改变):
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <vector> 5 using namespace std; 6 7 const int X = 350; 8 const int Y = 20; 9 int head[X]; 10 int sz[Y]; 11 bool visit[Y]; 12 vector<int> mark[Y]; 13 int e; 14 15 void init() 16 { 17 e = 0; 18 memset( head, -1, sizeof(head) ); 19 } 20 21 struct Edge 22 { 23 int v, next; 24 } edge[X * Y]; 25 26 void addEdge( int u, int v ) 27 { 28 edge[e].v = v; 29 edge[e].next = head[u]; 30 head[u] = e++; 31 } 32 33 int dfs( int u ) 34 { 35 for ( int i = head[u]; i != -1; i = edge[i].next ) 36 { 37 int v = edge[i].v; 38 if ( !visit[v] ) 39 { 40 visit[v] = 1; 41 if ( mark[v].size() < sz[v] ) 42 { 43 mark[v].push_back(u); 44 return 1; 45 } 46 else 47 { 48 for ( int j = 0; j < mark[v].size(); j++ ) 49 { 50 if ( dfs( mark[v][j] ) ) 51 { 52 mark[v][j] = u; 53 return 1; 54 } 55 } 56 } 57 } 58 } 59 return 0; 60 } 61 62 const int D = 7; 63 int nn[D]; 64 65 int main () 66 { 67 int _case; 68 scanf("%d", &_case); 69 while ( _case-- ) 70 { 71 int n; 72 scanf("%d", &n); 73 init(); 74 int tot = 0, wmax = -1, d, w; 75 for ( int i = 0; i < n; i++ ) 76 { 77 for ( int j = 0; j < D; j++ ) 78 { 79 scanf("%d", nn + j); 80 } 81 scanf("%d%d", &d, &w); 82 sz[i] = d; 83 tot += d; 84 wmax = max( wmax, w ); 85 for ( int j = 0; j < D; j++ ) 86 { 87 if ( nn[j] == 1 ) 88 { 89 for ( int k = 0; k < w; k++ ) 90 { 91 int num = k * 7 + j; 92 addEdge( num, i ); 93 } 94 } 95 } 96 } 97 for ( int i = 0; i < n; i++ ) 98 { 99 mark[i].clear(); 100 } 101 int res = 0; 102 for ( int i = 0; i < 7 * wmax; i++ ) 103 { 104 memset( visit, 0, sizeof(visit) ); 105 res += dfs(i); 106 } 107 if ( res == tot ) 108 { 109 puts("Yes"); 110 } 111 else 112 { 113 puts("No"); 114 } 115 } 116 return 0; 117 }