poj1689 Alice's Chance(最大流)

来源:互联网 发布:不可思议的夏天知乎 编辑:程序博客网 时间:2024/05/21 07:08

Description
Alice, a charming girl, have been dreaming of being a movie star for long. Her chances will come now, for several filmmaking companies invite her to play the chief role in their new films. Unfortunately, all these companies will start making the films at the same time, and the greedy Alice doesn’t want to miss any of them!! You are asked to tell her whether she can act in all the films.

As for a film,
it will be made ONLY on some fixed days in a week, i.e., Alice can only work for the film on these days;
Alice should work for it at least for specified number of days;
the film MUST be finished before a prearranged deadline.

For example, assuming a film can be made only on Monday, Wednesday and Saturday; Alice should work for the film at least for 4 days; and it must be finished within 3 weeks. In this case she can work for the film on Monday of the first week, on Monday and Saturday of the second week, and on Monday of the third week.

Notice that on a single day Alice can work on at most ONE film.

Input
The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case begins with a single line containing an integer N (1 <= N <= 20), the number of films. Each of the following n lines is in the form of “F1 F2 F3 F4 F5 F6 F7 D W”. Fi (1 <= i <= 7) is 1 or 0, representing whether the film can be made on the i-th day in a week (a week starts on Sunday): 1 means that the film can be made on this day, while 0 means the opposite. Both D (1 <= D <= 50) and W (1 <= W <= 50) are integers, and Alice should go to the film for D days and the film must be finished in W weeks.

Output
For each test case print a single line, ‘Yes’ if Alice can attend all the films, otherwise ‘No’.

Sample Input
2
2
0 1 0 1 0 1 0 9 3
0 1 1 1 0 0 0 6 4
2
0 1 0 1 0 1 0 9 4
0 1 1 1 0 0 0 6 2

Sample Output
Yes
No

Hint
A proper schedule for the first test case:

date Sun Mon Tue Wed Thu Fri Sat week1 film1 film2 film1 film1 week2 film1 film2 film1 film1 week3 film1 film2 film1 film1 week4 film2 film2 film2

分析:
在做过poj3686之后
这道题就相对简单了

最大流即可
建图:
源点向每一部电影连边,流量为最少天数
我们把每一周每一天都看成一个点,
只要一部电影在这天可以拍摄,那么电影就向这一天连边,流量为1
所有天向汇点连边,流量为1

最后跑dinic跑出来的答案如果和总的要求天数相等
那么输出Yes,否则输出No

tip

边的数组不要开小了

//这里写代码片#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int INF=0x33333333;const int N=3010;int cur[N],st[N],tot=-1,q[N*15],tou,wei,deep[N];int film[22][10],maxx,s,t,day[22],week[22],sum,n;struct node{    int x,y,v,nxt;};node way[N*N];inline void add(int u,int w,int z){    tot++;    way[tot].x=u;way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;    tot++;    way[tot].x=w;way[tot].y=u;way[tot].v=0;way[tot].nxt=st[w];st[w]=tot;}inline int bfs(int s,int t){    tou=wei=0;    memset(deep,-1,sizeof(deep));    for (int i=s;i<=t;i++) cur[i]=st[i];    deep[s]=1;    q[++wei]=s;    do    {        int r=q[++tou];        for (int i=st[r];i!=-1;i=way[i].nxt)            if (way[i].v&&deep[way[i].y]==-1)            {                deep[way[i].y]=deep[r]+1;                q[++wei]=way[i].y;            }        if (r==t) return 1;    }    while (tou<wei);    return deep[t]!=-1;}inline int dfs(int now,int t,int limit){    if (!limit||now==t) return limit;    int f,flow=0;    for (int i=cur[now];i!=-1;i=way[i].nxt)    {        cur[now]=i;        if (way[i].v&&deep[way[i].y]==deep[now]+1&&(f=dfs(way[i].y,t,min(limit,way[i].v))))        {            flow+=f;            limit-=f;            way[i].v-=f;            way[i^1].v+=f;            if (!limit) break;        }    }    return flow;}int doit(){    int ans=0;    while (bfs(s,t))        ans+=dfs(s,t,INF);    if (ans==sum) return 1;    else return 0;}inline int get(int x,int y){return 7*(x-1)+y;}void build(){    s=0;t=n+7*maxx+1;    for (int i=1;i<=n;i++)    {        add(s,i,day[i]);        for (int j=1;j<=week[i];j++)    //第j周的第k天             for (int k=1;k<=7;k++)                if (film[i][k])                   add(i,n+get(j,k),1);                 }    for (int i=n+1;i<t;i++) add(i,t,1);}int main(){    int T;    scanf("%d",&T);    while (T--)    {        memset(st,-1,sizeof(st));        tot=-1; sum=0; maxx=0;        scanf("%d",&n);        for (int i=1;i<=n;i++)        {            scanf("%d%d%d%d%d%d%d%d%d",&film[i][1],&film[i][2],&film[i][3],&film[i][4],&film[i][5],&film[i][6],&film[i][7],&day[i],&week[i]);            sum+=day[i];            maxx=max(maxx,week[i]);        }        build();        if (doit()) printf("Yes\n");        else printf("No\n");    }    return 0;}