POJ 1698 Alice's Chance

这道题本来是放在二分图多重匹配的专题上的……
但是在二分图上没怎么想出来,在网络流上一下子就有了想法……
因为本来二分图问题就是网络流的子问题么……我如是安慰自己……

题意:
一个刚出道的女演员有 n 部电影要拍,一部电影要拍多天,一天只能拍一部,给定每部电影安排的日期,和截止时间,问能否安排妥当。

思路:
这道题在网路流建图上一开始我是这样建的。

记录一周中每天限制周数最大的,作为电影与日期的流量,源点到电影流量为拍摄天数,日期到汇点容量为各自的限制周数。
这里有一个错误的地方,我拿个数据就很容易明白。

3
1 0 0 0 0 0 0 1 1
1 0 0 0 0 0 0 2 2
1 0 0 0 0 0 0 inf inf

实际上因为周数并不是很多,最多为 50 ,完全可以拆分成 50 × 7 个节点,这样反而更容易理解,也更容易写。

AC Code

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <string>

#define each(i, n) for (int(i) = 0; (i) < (n); (i)++)
#define reach(i, n) for (int(i) = (n - 1); (i) >= 0; (i)--)
#define range(i, st, en) for (int(i) = (st); (st) <= (en); (st)++)
#define rrange(i, st, en) for (int(i) = (en); (en) >= (st); (en)--)
#define fill(ary, num) memset((ary), (num), sizeof((ary)))

using namespace std;

const int maxn = 5000;
const int inf = 0x3f3f3f3f;

int n, m, st, en, idx, sum;
int level[maxn], cur[maxn];
int head[maxn];
bool vis[400];

struct node {
    int to;
    int nxt;
    int flow;
} edges[551000];

queue<int> que;

inline void addEdge(int u, int v, int flow)
{
    edges[idx].to = v;
    edges[idx].flow = flow;
    edges[idx].nxt = head[u];
    head[u] = idx++;

    edges[idx].to = u;
    edges[idx].flow = 0;
    edges[idx].nxt = head[v];
    head[v] = idx++;
}

bool bfs()
{
    while (!que.empty())
        que.pop();
    memset(level, -1, sizeof level);
    que.push(st);
    level[st] = 0;
    int u;
    while (!que.empty()) {
        u = que.front();
        que.pop();
        for (int id = head[u]; ~id; id = edges[id].nxt) {
            int v = edges[id].to;
            if (edges[id].flow && level[v] == -1) {
                level[v] = level[u] + 1;
                que.push(v);
            }
        }
    }
    return level[en] != -1;
}

int dfs(int u, int low)
{
    int cflow;
    if (u == en)
        return low;
    for (int& id = cur[u]; ~id; id = edges[id].nxt) {
        int v = edges[id].to;
        if (edges[id].flow && level[v] == level[u] + 1
            && (cflow = dfs(v, min(low, edges[id].flow)))) {
            edges[id].flow -= cflow;
            edges[id ^ 1].flow += cflow;
            return cflow;
        }
    }
    return 0;
}

int dinic()
{
    int ans = 0, cflow;
    while (bfs()) {
        for (int i = 0; i <= en; i++)
            cur[i] = head[i];
        while ((cflow = dfs(st, inf)))
            ans += cflow;
    }
    return ans;
}

void createGraph()
{
    memset(head, -1, sizeof head);
    memset(vis, false, sizeof vis);
    st = 0, en = 350 + n + 1, idx = 0, sum = 0;
    int cap, limit, status[10];
    for (int i = 1; i <= n; i++) {
        int ts = 350 + i;
        for (int j = 1; j <= 7; j++)
            scanf("%d", status + j);
        scanf("%d %d", &cap, &limit);
        sum += cap;
        addEdge(st, ts, cap);
        for (int j = 1; j <= 7; j++)
            if (status[j])
                for (int k = 0; k < limit; k++) {
                    addEdge(ts, k * 7 + j, 1);
                    if (!vis[k * 7 + j]) {
                        addEdge(k * 7 + j, en, 1);
                        vis[k * 7 + j] = true;
                    }
                }
    }
}

int main()
{
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        createGraph();
        if (dinic() == sum)
            puts("Yes");
        else
            puts("No");
    }
    return 0;
}