hdu 3572【网络流时间区间建图】

题目链接
题意:
有m个机器,有n个任务。每个任务必须>=Si 开始做,在<=Ei 完成,此任务持续时间为Pi。能否在规定时间内把任务做完?
分析:
网络流经典应用问题。建图:一个源点st和一个汇点end,源点与任务连接(任务编号1~n),每条路流量为Pi,任务与时间连接(时间编号n + 1~n + n),每条路流量为1,最后时间汇总到汇点,每条路流量为m。
这里写图片描述

#include <cstdio>  
#include <cstring>   
#include <queue>  
#include <algorithm>  
#define MAXN 2000+50
#define INF 0x3f3f3f
using namespace std;
int dist[MAXN], cur[MAXN], vis[MAXN], head[MAXN], top;

struct Edge {
    int to, cap, flow, next;
}edge[MAXN << 8];

void addedge(int a, int b, int c) {
    Edge E1 = {b, c, 0, head[a]};
    edge[top] = E1;
    head[a] = top++;
    Edge E2 = {a, 0, 0, head[b]};
    edge[top] = E2;
    head[b] = top++;
}

bool BFS(int start, int end) { 
    memset(dist, -1, sizeof(dist));  
    memset(vis, 0, sizeof(vis));  
    queue<int> Q; 
    Q.push(start);
    vis[start] = 1;
    dist[start] = 0; 
    while(!Q.empty()) {
        int u = Q.front();
        Q.pop();
        for(int i = head[u]; i != -1; i = edge[i].next) {
            Edge E = edge[i];
            if(!vis[E.to] && E.cap > E.flow) { 
                dist[E.to] = dist[u] + 1; 
                vis[E.to] = 1;
                if(E.to == end) return true;
                Q.push(E.to);
            }
        }
    }
    return false;
}

int DFS(int x, int cost, int end) { 
    if(x == end || cost == 0) return cost;
    int flow = 0, f;
    for(int& i = cur[x]; i != -1; i = edge[i].next) {
        Edge& E = edge[i];
        if(dist[E.to] == dist[x] + 1 &&  (f = DFS(E.to, min(cost, E.cap - E.flow), end)) > 0) { 
            E.flow += f;
            edge[i ^ 1].flow -= f;
            flow += f;
            cost -= f;
            if(cost == 0) break;
        }
    }
    return flow;
}

int Maxflow(int start, int end) {
    int flow = 0;
    while(BFS(start, end)) { 
        memcpy(cur, head, sizeof(head));
        flow += DFS(start, INF, end);
    }
    return flow;
}

int main() {
    int t, p = 1, n, m;;
    scanf("%d", &t);
    while(t--) {
        top = 0;
        memset(head, -1, sizeof(head));
        memset(edge, 0, sizeof(edge));
        int a, b, c, sum = 0, maxn = 0;
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= n; i++) { //注意建图,画出模型 
            scanf("%d %d %d", &c, &a, &b);
            maxn = max(b, maxn);
            sum += c;
            addedge(0, i, c);
            for(int j = a; j <= b; j++) {
                addedge(i, n + j, 1);
            }
        }
        for(int i = 1; i <= maxn; i++) {
            addedge(i + n, maxn + n + 1, m);
        }
        printf("Case %d: ", p++);
        if(Maxflow(0, maxn + n + 1) == sum) printf("Yes\n\n");
        else printf("No\n\n");
    }
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值