hdu 3572 Task Schedule

来源:互联网 发布:大数据与精准医疗 编辑:程序博客网 时间:2024/04/28 21:20

~~最大流~~

建图:把每个任务和每一天都看做一个点,添加源点和汇点。源点与每个任务之间连一条边,容量为完成该任务所需处理次数。若第i个任务可以在Si至Ei天处理,则由该任务向这些天分别连一条边,容量为1,表示此任务每天只能被处理一次。最后,从每一天连一条到汇点的边,容量为机器数M,表示每天可以处理M个任务。若求出的最大流等于所有任务需要处理的次数之和,说明能完成任务;否则,不能完成任务。

#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;const int maxn = 1111;const int maxm = 505000;const int oo = 1 << 30;int idx;int cur[maxn], pre[maxn];int dis[maxn], gap[maxn];int aug[maxn], head[maxn];struct Node{int u, v, w;int next;}edge[maxm];void addEdge(int u, int v, int w){    edge[idx].u = u;    edge[idx].v = v;    edge[idx].w = w;    edge[idx].next = head[u];    head[u] = idx++;    edge[idx].u = v;    edge[idx].v = u;    edge[idx].w = 0;    edge[idx].next = head[v];    head[v] = idx++;}int SAP(int s, int e, int n){    int max_flow = 0, v, u = s;    int id, mindis;    aug[s] = oo;    pre[s] = -1;    memset(dis, 0, sizeof(dis));    memset(gap, 0, sizeof(gap));    gap[0] = n; // 我觉得这一句要不要都行,因为dis[e]始终为0    for (int i = 0; i <= n; ++i)    {   // 初始化当前弧为第一条弧        cur[i] = head[i];    }    while (dis[s] < n)    {        bool flag = false;        if (u == e)        {            max_flow += aug[e];            for (v = pre[e]; v != -1; v = pre[v]) // 路径回溯更新残留网络            {                id = cur[v];                edge[id].w -= aug[e];                edge[id^1].w += aug[e];                aug[v] -= aug[e]; // 修改可增广量,以后会用到                if (edge[id].w == 0) u = v; // 不回退到源点,仅回退到容量为0的弧的弧尾            }        }        for (id = cur[u]; id != -1; id = edge[id].next)        {   // 从当前弧开始查找允许弧            v = edge[id].v;            if (edge[id].w > 0 && dis[u] == dis[v] + 1) // 找到允许弧            {                flag = true;                pre[v] = u;                cur[u] = id;                aug[v] = min(aug[u], edge[id].w);                u = v;                break;            }        }        if (flag == false)        {            if (--gap[dis[u]] == 0) break; /* gap优化,层次树出现断层则结束算法 */            mindis = n;            cur[u] = head[u];            for (id = head[u]; id != -1; id = edge[id].next)            {                v = edge[id].v;                if (edge[id].w > 0 && dis[v] < mindis)                {                    mindis = dis[v];                    cur[u] = id; // 修改标号的同时修改当前弧                }            }            dis[u] = mindis + 1;            gap[dis[u]]++;            if (u != s) u = pre[u]; // 回溯继续寻找允许弧        }    }    return max_flow;}int main(){    int t, n, m, pi, si, ei;    int Max, sum, source, sink, vn;    scanf("%d", &t);    for (int cas = 1; cas <= t; ++cas)    {        idx = 0;        memset(head, -1, sizeof(head));        sum = 0; source = 0; Max = 0;        scanf("%d %d", &n, &m);        for (int i = 1; i <= n; ++i)        {            scanf("%d %d %d", &pi, &si, &ei);            sum += pi;            Max = max(Max, ei);            addEdge(source, i, pi);            for (int j = si; j <= ei; ++j)            {                addEdge(i, n + j, 1);            }        }        sink = n + Max + 1;        vn = sink + 1;        for (int i = 1; i <= Max; ++i)        {            addEdge(n + i, sink, m);        }        if (SAP(source, sink, vn) == sum)            printf("Case %d: Yes\n\n", cas);        else printf("Case %d: No\n\n", cas);    }    return 0;}

原创粉丝点击