poj 1698 Alice‘s Chance
poj 1698 Alice‘s Chance
题目地址: http://poj.org/problem?id=1698
题意: 演员Alice ,面对n场电影,每场电影拍摄持续w周,每周特定几天拍摄,每场电影需要Alice到场的天数为d。 请问Alice是否可以参与所有的电影拍摄。
最近在学习最大流的算法。
(1), 最大流真的是一种神奇的算法,最大的亮点是最大流的可回溯性,其可回溯性体现在反向边的提出。
(2), 最大流的应用也是非常灵活的,其中一个体现在如何构建流量网络,本题采用逆向思维, 0 作为出发点, 1,2,... n作为电影点,出发点与电影点之间的流量是每一场电影需要Alice去拍摄的天数的,n+1, n+2, ..... 7*tw+n 这部分代表的是所有天数的点。每一部电影都连接该电影拍摄特定的天数(流量为1), 最后所有的天数(n+1, n+2, ... 7*tw+n)汇集到终点 7*tw+n+1 , 如果这个点的最大流与顾客总天数一致,说明ok。
// 1698 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int INF = 2100000000; const int maxn = 7*55 + 20 + 1 ; int n, mp[maxn][maxn], path[maxn], que[maxn*maxn]; int BFS(int src, int dest){ memset(path, -1, sizeof(path)); int cur, head = 0, tail = 0, minFlow = INF; que[tail++] = src; while(head < tail){ cur = que[head++]; if(cur == dest){ break; } for(int i=0; i<=dest; ++i){ if(path[i]==-1 && mp[cur][i]){ if(minFlow > mp[cur][i]){ minFlow = mp[cur][i]; } path[i] = cur; que[tail++] = i; } } } if(path[dest] == -1){ return -1; } return minFlow; } int MaxFlow(int src, int dest){ int cur, pre, flow, maxFlow = 0; while( (flow = BFS(src, dest)) != -1){ maxFlow += flow; cur = dest; while(cur != src){ pre = path[cur]; mp[pre][cur] -= flow; mp[cur][pre] += flow; cur = pre; } } return maxFlow; } int main(){ freopen("in.txt", "r", stdin); int test_num, d, w, sum, ans, tw=50, f[8]; scanf("%d", &test_num); while(test_num--){ memset(mp, 0, sizeof(mp)); sum = 0; scanf("%d", &n); for(int j=1; j<=n; ++j){ for(int i=1; i<=7; ++i){ scanf("%d", &f[i]); } scanf("%d %d", &d, &w); sum += d; mp[0][j] += d; for(int i=1; i<=7; ++i){ if(f[i] == 1){ for(int k=0; k<w; ++k){ mp[j][n + 7*k + i] += 1; } } } } for(int j=n+1; j<=n+tw*7; ++j){ mp[j][n+tw*7+1] += 1; } ans = MaxFlow(0, n+tw*7+1); if(ans == sum){ printf("Yes\n"); }else{ printf("No\n"); } } return 0; }