hdu 3572 Task Schedule ( 最大流 + 满流)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3572


Task Schedule

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 7440    Accepted Submission(s): 2307


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, the factory has to start processing it at or after day Si, process it for Pi days, and finish the task before or at day Ei. A machine can only work on one task at a time, and each task can be processed by at most one machine at a time. However, a task can be interrupted and processed on different machines on different days. 
Now she wonders whether he has a feasible schedule to finish all the tasks in time. She turns to you for help.
 

Input
On the first line comes an integer T(T<=20), indicating the number of test cases.

You are given two integer N(N<=500) and M(M<=200) on the first line of each test case. Then on each of next N lines are three integers Pi, Si and Ei (1<=Pi, Si, Ei<=500), which have the meaning described in the description. It is guaranteed that in a feasible schedule every task that can be finished will be done before or at its end day.
 

Output
For each test case, print “Case x: ” first, where x is the case number. If there exists a feasible schedule to finish all the tasks, print “Yes”, otherwise print “No”.

Print a blank line after each test case.
 

Sample Input
  
  
2 4 3 1 3 5 1 1 4 2 3 7 3 5 9 2 2 2 1 3 1 2 2
 

Sample Output
  
  
Case 1: Yes Case 2: Yes
 

Author
allenlowesy
 

Source
 

Recommend
zhouzeyong   |   We have carefully selected several similar problems for you:   3491  1533  3416  3081  3338 


题目大意:n个任务,m个机器,输入pi, si, ei 分别表示 第i个任务需要p天,从s到e的任意p天,求是否能完成

解析 :       最大流 + 满流问题,先学会EK或者Dinic求最大流,该题关键是如何建图,以0为源点,1~n为任务,边权为流量(这里是天数p),然后再将任务与天数对应起来,其中流量为1,再将天数与汇点对应起来,流量为机器数m(一天有m个机器在工作),最后判断是否满流,最后注意用引用减少时间,不然LTE


                    借鉴大牛博客:http://blog.csdn.net/discreeter/article/details/49004837


代码如下:

#include<iostream>
#include<algorithm>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<string>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#define N 1009
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 1<<30;
const double eps = 1e-8;
const double pi = acos(-1.0);
typedef long long LL;

typedef struct
{
    int to, c, rec;
}Q;

vector<Q> mp[N];
int pre[N], tt;
int vis[N];

void add(int u, int v, int w)
{
    Q e;
    e.to = v; e.c = w; e.rec = mp[v].size();
    mp[u].push_back(e);
    e.to = u; e.c = 0; e.rec = mp[u].size() - 1;
    mp[v].push_back(e);
}


int bfs()
{
    queue<int> q;
    memset(pre, 0, sizeof(pre));
    int i;
    q.push(0);
    pre[0] = 1;
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        int k = mp[u].size();
        for(i = 0; i < k; i++)
        {
            Q &e = mp[u][i];
            if(!pre[e.to] && e.c > 0)
            {
                pre[e.to] = pre[u] + 1;
                q.push(e.to);
            }
        }
    }
    return pre[tt] > 0;
}

int dfs(int u, int cur_flow)
{
    if(u == tt) return cur_flow;
    int k = mp[u].size();
    for(int &i = vis[u]; i < k; i++)
    {
        Q &e = mp[u][i];
        if(pre[u] + 1 == pre[e.to] && e.c > 0)
        {
            int f = dfs(e.to, min(cur_flow, e.c));
            if(f > 0)
            {
                e.c -= f;
                mp[e.to][e.rec].c += f;
                return f;
            }
        }
    }
    return 0;
}
int Dinic()
{
    int ans = 0, f;
     while(bfs())
     {
         memset(vis, 0, sizeof(vis)); //很重要,减少大量时间
         while((f = dfs(0, inf)))
            ans += f;
     }
     return ans;
}
int main()
{
    int i, j, s, e, p, m ,n;
    int t, cnt = 0;
    cin >> t;
    while(t--)
    {
        scanf("%d%d", &n, &m);
        int sum = 0; tt = 0;
        for(i = 1; i <= n; i++)
        {
            scanf("%d%d%d", &p, &s, &e);
            add(0, i, p);
            sum += p;
            tt = max(tt, e);
            for(j = s; j <= e; j++) add(i, j + n, 1);
        }
        tt = tt + n + 1;
        for(i = n + 1; i < tt; i++) add(i, tt, m);
        int ans = Dinic();
        if(sum == ans) printf("Case %d: Yes\n\n", ++cnt);
        else printf("Case %d: No\n\n", ++cnt);

        for(i = 0; i < N; i++) mp[i].clear();
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值