HDU - 3572 Task Schedule (最大流)

题目大意:有N个任务,M台机器。

每个任务有相应的起始时间,截至时间和完成时间

每台机器一小时可以做1个单位的工作量,每个任务的完成可以不连续,但每次只能由一台机器完成

问能否完成所有任务

解题思路:因为只有500分钟,所以可以将每分钟都设成1条边,连向超级汇点,容量为M

每个任务连接向超级源点,容量为完成时间

接着将任务连接像时间(分钟),连接的条件为,该时间在起始时间和截止时间这个区间之内

这样图就构成了

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define N 1010
#define INF 0x3f3f3f3f

struct Edge {
    int from, to, cap, flow;
    Edge() {}
    Edge(int from, int to, int cap, int flow): from(from), to(to), cap(cap), flow(flow) {}
};

struct ISAP {
    int p[N], num[N], cur[N], d[N];
    int t, s, n, m;
    bool vis[N];

    vector<int> G[N];
    vector<Edge> edges;

    void init(int n) {
        this->n = n;
        for (int i = 0; i <= n; i++) {
            G[i].clear();
            d[i] = INF;
        }
        edges.clear();
    }

    void AddEdge(int from, int to, int cap) {
        edges.push_back(Edge(from, to, cap, 0));
        edges.push_back(Edge(to, from, 0, 0));
        m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }

    bool BFS() {
        memset(vis, 0, sizeof(vis));

        queue<int> Q;
        d[t] = 0;
        vis[t] = 1;
        Q.push(t);

        while (!Q.empty()) {
            int u = Q.front();
            Q.pop();

            for (int i = 0; i < G[u].size(); i++) {
                Edge &e = edges[G[u][i] ^ 1];
                if (!vis[e.from] && e.cap > e.flow) {
                    vis[e.from] = true;
                    d[e.from] = d[u] + 1;
                    Q.push(e.from);
                }
            }
        }
        return vis[s];
    }

    int Augment() {
        int u = t, flow = INF;
        while (u != s) {
            Edge &e = edges[p[u]];
            flow = min(flow, e.cap - e.flow);
            u = edges[p[u]].from;
        }

        u = t;
        while (u != s) {
            edges[p[u]].flow += flow;
            edges[p[u] ^ 1].flow -= flow;
            u = edges[p[u]].from;
        }
        return flow;
    }

    int Maxflow(int s, int t) {
        this->s = s; this->t = t;
        int flow = 0;
        BFS();
        if (d[s] > n)
            return 0;

        memset(num, 0, sizeof(num));
        memset(cur, 0, sizeof(cur));
        for (int i = 0; i < n; i++)
            if (d[i] < INF)
                num[d[i]]++;
        int u = s;

        while (d[s] <= n) {
            if (u == t) {
                flow += Augment();
                u = s;
            }
            bool ok = false;
            for (int i = cur[u]; i < G[u].size(); i++) {
                Edge &e = edges[G[u][i]];
                if (e.cap > e.flow && d[u] == d[e.to] + 1) {
                    ok = true;
                    p[e.to] = G[u][i];
                    cur[u] = i;
                    u = e.to;
                    break;
                }
            }

            if (!ok) {
                int Min = n ;
                for (int i = 0; i < G[u].size(); i++) {
                    Edge &e = edges[G[u][i]];
                    if (e.cap > e.flow)
                        Min = min(Min, d[e.to]);
                }
                if (--num[d[u]] == 0)
                    break;
                num[d[u] = Min + 1]++;
                cur[u] = 0;
                if (u != s)
                    u = edges[p[u]].from;
            }
        }
        return flow;
    }
};

ISAP isap;
int n, m, cas = 1;
int S[N], E[N], P[N]; 

void solve() {
    scanf("%d%d", &n, &m);
    int Max = -1, Sum = 0;
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d", &P[i], &S[i], &E[i]);
        Max = max(Max, E[i]);
        Sum += P[i];
    }
    int s = 0, t = n + Max + 1;
    isap.init(t);
    for (int i = 1; i <= Max; i++) {
        isap.AddEdge(i + n, t, m);
    }

    for (int i = 1; i <= n; i++) {
        isap.AddEdge(s, i, P[i]);
        for (int j = S[i]; j <= E[i]; j++) {
            isap.AddEdge(i, j + n, 1);
        }
    }
    printf("Case %d: ", cas++);
    if (Sum == isap.Maxflow(s, t))
        printf("Yes\n\n");
    else
        printf("No\n\n");
}

int main() {
    int test;
    scanf("%d", &test);
    while (test--) {
        solve();

    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-14 18:44:40

HDU - 3572 Task Schedule (最大流)的相关文章

HDU 3572 Task Schedule (最大流)

C - Task Schedule Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 3572 Description Our geometry princess XMM has stoped her study in computational geometry to concentrate on her newly opened fac

hdu 3572 Task Schedule 最大流 Dinic算法,,卡时间。。建图非常有讲究

Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4617    Accepted Submission(s): 1513 Problem Description Our geometry princess XMM has stoped her study in computational geometry t

hdu 3572 Task Schedule(最大流)

hdu 3572 Task Schedule Description Our geometry princess XMM has stoped her study in computational geometry to concentrate on her newly opened factory. Her factory has introduced M new machines in order to process the coming N tasks. For the i-th tas

HDU 3572 Task Schedule(ISAP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3572 题意:m台机器,需要做n个任务.第i个任务,你需要使用机器Pi天,且这个任务要在[Si  ,  Ei]区间内完成才有效.对于一个任务,只能由一个机器来完成,一个机器同一时间只能做一个任务.当然,一个任务可以分成几段不连续的时间来完成.问,能否做完全部任务. 题意很清晰,也就是判断是否是满流. 对于网络流问题,模板大家都有,关键在于如何建图(详见资料) 思路:今天问了龙哥,对建图有了一定的了解,

hdu 3572 Task Schedule(网络流 dinic算法)

Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3412    Accepted Submission(s): 1197 Problem Description Our geometry princess XMM has stoped her study in computational geometry t

HDU 3572 Task Schedule(拆点+最大流dinic)

Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7753    Accepted Submission(s): 2381 Problem Description Our geometry princess XMM has stoped her study in computational geometry t

hdu 3572 Task Schedule

Task Schedule Problem Description Our geometry princess XMM has stoped her study in computational geometry to concentrate on her newly opened factory. Her factory has introduced M new machines in order to process the coming N tasks. For the i-th task

HDU 3572 Task Schedule(最大流判断满流)

https://vjudge.net/problem/HDU-3572 题意: 有N个作业和M台机器,每个作业都有一个持续时间P,工作的日期为S~E.作业可以断断续续的在不同机器上做,每台机器每次只可以处理一个作业.判断是否可以在作业的工作日期内完成所有作业. 思路: 建立源点0和汇点t,因为天数最多为500,所有我们将日期的编号定为1~500,作业的编号为500+i. 对于每个作业,与源点0相连,容量为P,意味着它必须走完这P容量才能完成这作业.与S~E相连,容量为1.日期与汇点相连,容量为m

hdu 3572 Task Schedule【 最大流 】

求出最大流,再判断是否满流 先不理解为什么要这样建图 后来看了这一篇题解 http://blog.csdn.net/u012350533/article/details/12361003 把0看做源点st 把每一个任务看做一个点 st到每个任务连边,容量为p,表示任务完成需要的天数 每个任务到每个任务的开始至结束时间连边,容量为1,表示这个任务可以在这些天完成 每一天向汇点ed连边,容量为m,表示一天最多运行m个任务 然后判断最大流是否等于执行完所有任务所需要的时间 1 #include<cst