hdu 3572 Task Schedule网络流_最大流判满流

Task Schedule

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


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  3549  3081 

题意:有M台机器,N个任务每个任务完成时间为pi,必须在si-ei这段区间完成,每一天只能用一台机器运转第Ni个任务,即一个任务一天不能被多台机器运行。

网络流跑最大流判满流,每一天看做一个点,建一个源点start,汇点end,start连接每一天的点,权值为M,因为每一天最多有M台机器能运行,对于某一天在一个任务的时间区域类则连接,权值赋为1,因为对于某一个任务一天最多能执行完一个单位的时间,第Ni个任务连接汇点end,权值赋为pi,因为最多能被执行pi个单位时间。

dinic:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>

using namespace std;

#define XINF INT_MAX
#define INF 0x3F3F3F3F
typedef long long ll;
typedef unsigned long long ull;
#define N 6500
const ll MOD = 998244353;
const int MAXN=6500;//点数的最大值
const int MAXM=205000;//边数的最大值
struct Edge
{
    int from, to, cap;
    int next;
}edge[MAXM];
int head[N], cnt;
int dep[N];
int n, m;
int s, e, p;
void init()
{
    cnt = 0;
    memset(head, -1, sizeof(head));
}

void addedge(int u, int v, int cap)
{
    edge[cnt].from = u;
    edge[cnt].to = v;
    edge[cnt].cap = cap;
    edge[cnt].next = head[u];
    head[u] = cnt++;
    edge[cnt].from = v;
    edge[cnt].to = u;
    edge[cnt].cap = 0;
    edge[cnt].next = head[v];
    head[v] = cnt++;
}
int BFS(int start,int end)
{
    int que[MAXN];
    int front,rear;
    front=rear=0;
    memset(dep,-1,sizeof(dep));
    que[rear++]=start;
    dep[start]=0;
    while(front!=rear)
    {
        int u=que[front++];
        if(front==MAXN)front=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(edge[i].cap>0&&dep[v]==-1)
            {
                dep[v]=dep[u]+1;
                que[rear++]=v;
                if(rear>=MAXN)rear=0;
                if(v==end)return 1;
            }
        }
    }
    return 0;
}
int dinic(int start,int end)
{
    int res=0;
    int top;
    int stack[MAXN];//stack为栈,存储当前增广路
    int cur[MAXN];//存储当前点的后继
    while(BFS(start,end))
    {
        memcpy(cur,head,sizeof(head));
        int u=start;
        top=0;
        while(1)
        {
            if(u==end)
            {
                int min=INF;
                int loc;
                for(int i=0;i<top;i++)
                  if(min>edge[stack[i]].cap)
                  {
                      min=edge[stack[i]].cap;
                      loc=i;
                  }
                for(int i=0;i<top;i++)
                {
                    edge[stack[i]].cap-=min;
                    edge[stack[i]^1].cap+=min;
                }
                res+=min;
                top=loc;
                u=edge[stack[top]].from;
            }
            for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)
              if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to])
                 break;
            if(cur[u]!=-1)
            {
                stack[top++]=cur[u];
                u=edge[cur[u]].to;
            }
            else
            {
                if(top==0)break;
                dep[u]=-1;
                u=edge[stack[--top]].from;
            }
        }
    }
    return res;
}
int main()
{
    int T, u, v, w, p, s, e;
    scanf("%d", &T);
    int Case = 1;
    while(T--) {
        init();
        scanf("%d%d", &n, &m);
        int maxn = -INF;
        int start = 0, t = n+1;
        int sum = 0;
        for(int i = 1; i <= n; i++) {
            scanf("%d%d%d", &p, &s, &e);
            sum += p;
            maxn = max(maxn, e);
            addedge(i, t, p);
            //addedge(start, i, p);
            for(int j = s; j <= e; ++j) {
                //addedge(start, n+j+1, m);
                addedge(n+j+1, i, 1);
              //  addedge(start, n+j+1, m);
                //addedge(i, n+j+1, 1);
               // addedge(n+j+1, t, m);
            }
        }
      for(int i = 1; i <= maxn; i++)
            addedge(start, i+n+1, m);

       int ans = dinic(start, t);
        if(ans == sum)
            printf("Case %d: Yes\n\n", Case++);
        else
            printf("Case %d: No\n\n", Case++);
    }
    return 0;
}

SAP:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>


using namespace std;

#define XINF INT_MAX
#define INF 0x3F3F3F3F
typedef long long ll;
typedef unsigned long long ull;

const ll MOD = 998244353;
const int MAXN=201000;//点数的最大值
const int MAXM=20000500;//边数的最大值

struct Edge
{
    int to, next, cap, flow;
} edge[MAXN*10];
int tol;
int head[MAXN];
int gap[MAXN], dep[MAXN], pre[MAXN], cur[MAXN];
int n, m;
void init()
{
    tol = 0;
    memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int w, int rw = 0)
{
    edge[tol].to = v;edge[tol].cap = w;edge[tol].next = head[u];edge[tol].flow = 0;head[u] = tol++;
    edge[tol].to = u;edge[tol].cap = rw;edge[tol].next = head[v];edge[tol].flow = 0;head[v] = tol++;
}
int sap(int start, int end, int N)
{
    memset(gap, 0, sizeof(gap));
    memset(dep, 0, sizeof(dep));
    memcpy(cur, head, sizeof(head));
    int u = start;
    pre[u] = -1;
    gap[0] = N;//N所有的点个数包括源点汇点
    int ans = 0;
    while(dep[start] < N)
    {
        if(u == end)
        {
            int Min = INF;
            for(int i = pre[u]; i != -1; i = pre[edge[i^1].to])
                if(Min > edge[i].cap - edge[i].flow)
                    Min = edge[i].cap - edge[i].flow;
            for(int i = pre[u]; i != -1; i = pre[ edge[i ^ 1].to ])
            {
                edge[i].flow += Min;
                edge[i^1].flow -= Min;
            }
            u = start;
            ans += Min;
            continue;
        }
        bool flag = false;
        int v;
        for(int i = cur[u]; i != -1; i = edge[i].next)
        {
            v = edge[i].to;
            if(edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u])
            {
                flag = true;
                cur[u] = pre[v] = i;
                break;
            }
        }
        if(flag)
        {
            u = v;
            continue;
        }
        int Min = N;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)
            {
                Min = dep[edge[i].to];
                cur[u] = i;
            }
        }
        gap[dep[u]]--;
        if(!gap[dep[u]])
            return ans;
        dep[u] = Min+1;
        gap[dep[u]]++;
        if(u != start)
            u = edge[ pre[u] ^ 1 ].to;
    }
    return ans;
}

int main()
{
    int T, u, v, w, p, s, e;
    scanf("%d", &T);
    int Case = 1;
    while(T--) {
        init();
        scanf("%d%d", &n, &m);
        int maxn = -INF;
        int start = 0, t = n+1;
        int sum = 0;
        for(int i = 1; i <= n; i++) {
            scanf("%d%d%d", &p, &s, &e);
            sum += p;
            maxn = max(maxn, e);
            addedge(i, t, p);
            //addedge(start, i, p);
            for(int j = s; j <= e; ++j) {
                //addedge(start, n+j+1, m);
                addedge(n+j+1, i, 1);
              //  addedge(start, n+j+1, m);
                //addedge(i, n+j+1, 1);
               // addedge(n+j+1, t, m);
            }
        }
      for(int i = 1; i <= maxn; i++)
            addedge(start, i+n+1, m);

        int ans = sap(start, t, n+maxn+2);

        if(ans == sum)
            printf("Case %d: Yes\n\n", Case++);
        else
            printf("Case %d: No\n\n", Case++);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值