• POJ 1698 Alice's Chance


    题目:Alice 要拍电影,每一天只能参与一部电影的拍摄,每一部电影只能在 Wi 周之内的指定的日子拍摄,总共需要花 Di 天时间,求能否拍完所有电影。

    典型的二分图多重匹配,这里用了最大流的 dinic 算法。构图:源点向每部电影流容量为 Di 的边,电影向允许的日期流容量为 1 的边,每一天向汇点流容量为 1 的边。跑一次最大流,如果最大流等于 D,那么就可以。

    一开始用了多路增广忘了把流量为零的 d 设为 -1……悲剧……TLE 了。

    代码:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    using namespace std;
    
    const int MAXV = 520, FILM = 400, MAXE = 15000, INF = 0x3f3f3f3f;
    struct edge{
        int to, cap, next;
        edge(){};
        edge(int to_, int cap_, int next_):to(to_), cap(cap_), next(next_){};
    } es[MAXE];
    int head[MAXV], d[MAXV], que[MAXV], tot, tmp[8];
    
    void init(){
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    
    inline void add2(const int &a, const int &b, const int &cap){
    //  printf("%d---%d: %d
    ", a, b, cap);
        es[tot] = edge(b, cap, head[a]); head[a] = tot++;
        es[tot] = edge(a,   0, head[b]); head[b] = tot++;
    }
    
    bool bfs(int s, int t){
        memset(d, -1, sizeof(d));
        d[s] = 0;
        int hh = 0, tt = 1;
        que[0] = s;
        while(hh < tt){
            int u = que[hh++];
            if(u == t)return true;
            for(int i = head[u]; ~i; i = es[i].next){
                int v = es[i].to;
                if(d[v] == -1 && es[i].cap){
                    d[v] = d[u] + 1;
                    que[tt++] = v;
                }
            }
        }
        return false;
    }
    
    int dfs(int s, int t, int low){
        if(s == t) return low;
        int ret = 0;
        for(int i = head[s]; ~i; i = es[i].next){
            int v = es[i].to, f = es[i].cap;
            if(d[v] == d[s] + 1 && f && (f = dfs(v, t, min(low - ret, f)))){
                es[i].cap -= f;
                es[i^1].cap += f;
                ret += f;           //多路增广 
                if(ret == low) break;
            }
        }
        if(!ret) d[s] = -1; //这里剪枝非常重要 
        return ret;
    }
    
    int dinic(int s, int t){
        int ans = 0;
        while(bfs(s, t)){
            ans += dfs(s, t, INF);
        }
        return ans;
    }
    
    int main(){
        freopen("in.txt", "r", stdin);
        int T, N, D, W;
        scanf("%d", &T);
        while(T--){
            init();
            int sum = 0, day = 0;
            scanf("%d", &N);
            for(int i = 0; i < N; ++i){
                for(int j = 1; j <= 7; ++j) scanf("%d", &tmp[j]);
                scanf("%d%d", &D, &W);
                day = max(day, W);
                add2(0, FILM + i, D);
                sum += D;
                for(int w = 0; w < W; ++w){
                    for(int j = 1; j <= 7; ++j){
                        if(tmp[j]) add2(FILM + i, w * 7 + j, 1);
                    }
                }
            }
            for(int i = day * 7; i > 0; --i){
                add2(i, 500, 1);
            }
            int ans = dinic(0, 500);
            if(ans == sum) printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
  • 相关阅读:
    vue+element-ui实现前端分页
    element-UI中table表格的row-click事件怎么获取一行数据的id
    使用一个for循环将N*N的二维数组的所有值置1
    http常见的状态码
    反转一个英文句子中的单词,并且对应位置大小写不改变
    用一条SQL语句查出每门课都大于80分的学生的姓名
    平滑重启原理及平滑更新
    php之命名空间
    php之trait-实现多继承
    C入门之一
  • 原文地址:https://www.cnblogs.com/will7101/p/6506693.html
Copyright © 2020-2023  润新知