poj 1698 Alice's Chance 【最大流 判断是否满流】

Alice's Chance
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 6386   Accepted: 2609

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, 
  1. it will be made ONLY on some fixed days in a week, i.e., Alice can only work for the film on these days; 
  2. Alice should work for it at least for specified number of days; 
  3. 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

题意:一个女孩想要参加N部电影的演出。

对每部电影 给出三条信息

1,演出的时间—— 有7个整数,若Fi为1代表在星期 i 演出一天,Fi为0时说明星期 i 不演出。

2,该女孩在电影里面演出的天数D——她若要参加这个电影演出天数必须达到D;

3,电影上演的时限W,表示该电影最多会持续W个星期。

对于一部电影,每个星期的演出时间是固定的。现在问你这个女孩能不能参加所有的电影。

简单最大流,直接说下建图。

建图:设置超级源点source,超级汇点sink

1,source向所有电影建边,容量为每部电影需要演出的天数D。

2,每部电影向它可以演出的时间点建边,容量为1。

3,所有时间点向sink建边,容量为1,表示一个时间点只能演出一部电影。

最后判断从source流出的流量和流入sink的流量是否相等就行了。

AC代码:

#include 
#include 
#include 
#include 
#define MAXN 400//不会超400
#define MAXM 50000+10
#define INF 0x3f3f3f3f
using namespace std;
struct Edge
{
    int from, to, cap, flow, next;
};
Edge edge[MAXM];
int head[MAXN], edgenum;
int dist[MAXN], cur[MAXN];
bool vis[MAXN];
int N;
int source, sink;//超级源点 超级汇点
void init()
{
    edgenum = 0;
    memset(head, -1, sizeof(head));
}
void addEdge(int u ,int v, int w)
{
    int i;
    for(i = head[u]; i != -1; i = edge[i].next)//去重边
    {
        if(edge[i].to == v)
            break;
    }
    if(i != -1)
    {
        edge[i].cap += w;
        return ;
    }
    Edge E1 = {u, v, w, 0, head[u]};
    edge[edgenum] = E1;
    head[u] = edgenum++;
    Edge E2 = {v, u, 0, 0, head[v]};
    edge[edgenum] = E2;
    head[v] = edgenum++;
}
int sum;//记录总流量
int need[10];//对当前的电影 记录第i天是否需要去
void getMap()
{
    int a, b, c;
    int D, W;
    int MaxW;//所有电影中 延续最长的星期数
    sum = MaxW = 0;
    source = 0, sink = 399;
    for(int i = 1; i <= N; i++)
    {
        for(int j = 1; j <= 7; j++)//七天
            scanf("%d", &need[j]);
        scanf("%d%d", &D, &W);//需要去的天数 延续的星期
        MaxW = max(W, MaxW);
        addEdge(source, i, D);//源点到每场电影建边 容量为需要去的天数
        sum += D;//累加流量
        for(int j = 1; j <= 7; j++)
        {
            if(need[j])//若需要去 则向每个星期的这一天建边
            {
                for(int k = 1; k <= W; k++)
                    addEdge(i, (k-1)*7+N+j, 1);
            }
        }
    }
    for(int i = 1; i <= MaxW; i++)//所有时间点 向sink建边
    {
        for(int j = 1; j <= 7; j++)
            addEdge((i-1)*7+N+j, sink, 1);
    }
}
bool BFS(int s, int t)
{
    queue Q;
    memset(dist, -1, sizeof(dist));
    memset(vis, false, sizeof(vis));
    dist[s] = 0;
    vis[s] = true;
    Q.push(s);
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            Edge E = edge[i];
            if(!vis[E.to] && E.cap > E.flow)
            {
                dist[E.to] = dist[u] + 1;
                if(E.to == t) return true;
                vis[E.to] = true;
                Q.push(E.to);
            }
        }
    }
    return false;
}
int DFS(int x, int a, int t)
{
    if(x == t || a == 0) return a;
    int flow = 0, f;
    for(int &i = cur[x]; i != -1; i = edge[i].next)
    {
        Edge &E = edge[i];
        if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(a, E.cap-E.flow), t)) > 0)
        {
            edge[i].flow += f;
            edge[i^1].flow -= f;
            flow += f;
            a -= f;
            if(a == 0) break;
        }
    }
    return flow;
}
int Maxflow(int s, int t)
{
    int flow = 0;
    while(BFS(s, t))
    {
        memcpy(cur, head, sizeof(head));
        flow += DFS(s, INF, t);
    }
    return flow;
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &N);
        init();
        getMap();
        if(Maxflow(source, sink) == sum)//满流
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}


你可能感兴趣的:(网络流)