POJ 1698 Alice's Chance 网络流(水

来源:互联网 发布:程序员兼职 编辑:程序博客网 时间:2024/06/02 02:09

题目链接:点击打开链接

题目大意:   有个人想拍n部电影,每部电影限定每周哪几天可以拍

                  并且必须在第ki周之前把这部电影拍完,问能否拍完n部电影

解题思路:  把每部电影当作一个顶点,源点指向这些顶点,容量为该电影需要拍多少天

                  然后把每一天都当作顶点,某个工作可以在这天完成就连容量为1大边

                  每天的顶点指向汇点,容量也为1

                  最后求出最大流,满流则说明可以完成这些工作



啦啦啦

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>template <class T>inline bool rd(T &ret) {    char c; int sgn;    if(c=getchar(),c==EOF) return 0;    while(c!='-'&&(c<'0'||c>'9')) c=getchar();    sgn=(c=='-')?-1:1;    ret=(c=='-')?0:(c-'0');    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');    ret*=sgn;    return 1;}template <class T>inline void pt(T x) {    if (x <0) {        putchar('-');        x = -x;    }    if(x>9) pt(x/10);    putchar(x%10+'0');}using namespace std;//点标 [0,n]const int N = 20+50*7+100;const int M = 500010;const int INF = ~0u >> 2;template<class T>struct Max_Flow {    int n;    int Q[N], sign;    int head[N], level[N], cur[N], pre[N];    int nxt[M], pnt[M], E;    T cap[M];    void Init(int n) {        this->n = n+1;        E = 0;        std::fill(head, head + this->n, -1);    }    //有向rw 就= 0    void add(int from, int to, T c) {        pnt[E] = to;        cap[E] = c;        nxt[E] = head[from];        head[from] = E++;        pnt[E] = from;        cap[E] = 0;        nxt[E] = head[to];        head[to] = E++;    }    bool Bfs(int s, int t) {        sign = t;        std::fill(level, level + n, -1);        int *front = Q, *tail = Q;        *tail++ = t; level[t] = 0;        while(front < tail && level[s] == -1) {            int u = *front++;            for(int e = head[u]; e != -1; e = nxt[e]) {                if(cap[e ^ 1] > 0 && level[pnt[e]] < 0) {                    level[pnt[e]] = level[u] + 1;                    *tail ++ = pnt[e];                }            }        }        return level[s] != -1;    }    void Push(int t, T &flow) {        T mi = INF;        int p = pre[t];        for(int p = pre[t]; p != -1; p = pre[pnt[p ^ 1]]) {            mi = std::min(mi, cap[p]);        }        for(int p = pre[t]; p != -1; p = pre[pnt[p ^ 1]]) {            cap[p] -= mi;            if(!cap[p]) {                sign = pnt[p ^ 1];            }            cap[p ^ 1] += mi;        }        flow += mi;    }    void Dfs(int u, int t, T &flow) {        if(u == t) {            Push(t, flow);            return ;        }        for(int &e = cur[u]; e != -1; e = nxt[e]) {            if(cap[e] > 0 && level[u] - 1 == level[pnt[e]]) {                pre[pnt[e]] = e;                Dfs(pnt[e], t, flow);                if(level[sign] > level[u]) {                    return ;                }                sign = t;            }        }    }    T Dinic(int s, int t) {        pre[s] = -1;        T flow = 0;        while(Bfs(s, t)) {            std::copy(head, head + n, cur);            Dfs(s, t, flow);        }        return flow;    }};Max_Flow <int>F;int n;void work(){    rd(n);    int from = 0, to = n + 50*7 +1;    F.Init(to);    int all = 0;    for(int i = 1, d, w; i <= n; i++)    {        int a[8];        for(int j = 1; j <= 7; j++)rd(a[j]);        rd(d); rd(w);        all += d;        F.add(from, i, d);        for(int week = 0; week < w; week++)            for(int j = 1; j <= 7; j++)                if(a[j])                    F.add(i, n+week*7+j, 1);    }    for(int i = 0; i < 50; i++)        for(int j = 1; j <= 7; j++)            F.add(n+i*7+j, to, 1);    all == F.Dinic(from, to)?puts("Yes"):puts("No");}int main(){    int T; rd(T);    while(T--)        work();    return 0;}


0 0