POJ-1698 Alice's Chance(最大流)

来源:互联网 发布:java ftp 上传文件 编辑:程序博客网 时间:2024/06/05 23:41

题意:

Alice去拍电影,每一部电影只可以在某一天进行拍摄(星期一到星期日,1表示可以,0表示不可以),以及这部电影需要拍摄的总天数和在第几个星期前需要拍摄完成,且Alice每天只能拍一部电影。问Alice能够拍上全部的电影吗?可以输出Yes,否则输出No。

构图:

建立一个源点S和一个汇点T,然后因为Alice能选择某个日子进行拍电影,所以所有日子都可以与S连边(S->),再根据哪些日子可用来拍哪个电影去进行日子与电影节点的建边,因为一个日子只能给某个电影提供1天的工作,所以权值为1,然后电影与汇点进行连边,因为要限制电影消耗的日子,即如果某个电影已经有足够的时间了,不必浪费时间再流给它,所以电影与汇点进行连边权值为电影需要拍的日子,从而限制了该电影有足够日子后对日子的浪费。

将题目条件一一罗列出来,然后根据题目语义将问题抽象成网络图进行问题解决。(链接)


本题EK也可以过,只给出SAP方法代码:

#include <algorithm>#include <string.h>#include <cstdio>#include <queue>using namespace std;const int inf = 0x3f3f3f3f;const int maxn = 377;const int maxm = maxn*100;//一定要仔细计算一下边的数量 const int BAS = 50*7;struct node{int v, w, next;} edge[maxm];int no, head[maxn], now[maxn];int n;int day[10], sum;int N, S, T;int dis[maxn], pre[maxn], rec[maxn], gap[maxn];queue<int> q;inline void init(){no = 0;memset(head, -1, sizeof head);}inline void add(int u, int v, int w){edge[no].v = v, edge[no].w = w;edge[no].next = head[u]; head[u] = no++;edge[no].v = u, edge[no].w = 0;edge[no].next = head[v]; head[v] = no++;}int mapping(){int d, w, flag, judge;scanf("%d", &n); flag = 1; sum = 0;S = BAS+21, T = BAS+22; N = 0;for(int j = 1; j <= n; ++j){judge = 0;for(int i = 1; i <= 7; ++i) {scanf("%d", &day[i]);if(day[i]) ++judge;}scanf("%d %d", &d, &w); sum += d;for(int i = 1; i <= 7; ++i){if(day[i]) for(int k = 0; k < w; ++k) add(i+k*7, BAS+j, 1);}add(BAS+j, T, d);N = max(w, N);if(judge*w < d) flag = 0;//特判,当一个电影可用的所有时间小于要求时间直接No }for(int i = 1; i <= 7; ++i)for(int k = 0; k < N; ++k) add(S, i+k*7, 1);N *= 7;if(flag) return 1;return 0;}void prepare(int S, int T){memset(gap, 0, sizeof gap);for(int i = 1; i <= N; ++i) now[i] = head[i];for(int i = 1; i <= 22; ++i) now[BAS+i] = head[BAS+i];while(!q.empty()) q.pop();memset(dis, 0x3f, sizeof dis);dis[T] = 0; q.push(T);while(!q.empty()){int top = q.front(); q.pop();++gap[dis[top]];for(int k = head[top]; k != -1; k = edge[k].next){if(edge[k^1].w && dis[edge[k].v] == inf)dis[edge[k].v] = dis[top]+1, q.push(edge[k].v);}}}int SAP(int S, int T){int k, top = S, ans = 0, flow = inf;prepare(S, T);pre[S] = S;while(dis[S] < maxn)//切记此处与节点数比较,因为通过方向变会造成距离可能达到节点数 {if(top == T){ans += flow;for(; top != S; top = pre[top]){edge[rec[top]].w -= flow;edge[rec[top]^1].w += flow;}flow = inf;}for(k = now[top]; k != -1; k = edge[k].next){if(edge[k].w && dis[top] == dis[edge[k].v]+1){rec[edge[k].v] = k; pre[edge[k].v] = top;flow = min(flow, edge[k].w);now[top] = k; top = edge[k].v;break;}}if(k == -1){if(--gap[dis[top]] == 0) break;k = now[top] = head[top];int mins = maxn;for(; k != -1; k = edge[k].next)if(edge[k].w && mins > dis[edge[k].v]) mins = dis[edge[k].v];++gap[dis[top] = mins+1];top = pre[top];}}return ans;}int main(){int t, u, v, w;scanf("%d", &t);for(int _ = 1; _ <= t; ++_){init();if(!mapping()) puts("No");else{if(SAP(S, T) >= sum) puts("Yes");else puts("No");}}return 0;}

继续加油~

原创粉丝点击