hdu 3572(构图+最大流)

Task Schedule

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


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
 
题意:n个任务m台机器,其中完成第i个任务需要p[i]天,需要在第s[i]天或者其之后开始,需要在第e[i]天或者其之前完成,任务可以随时开始或者停止,问在给定的条件下能否完成所有的任务。
题解:构造超级源点以及超级汇点,超级源点向每个i点连一条容量为p[i]的边,每一个i点向其起始天和完成天区间内的每一天连一条容量为1的边,然后所有的天都向所有的机器连一条容量为1的边,最后所有的机器向汇点连一条无穷大的边,做一次最大流,如果max_flow == sum(p[i]),则证明能够完成所有的任务,别把下标弄混了。。弄错了一个下标,WA了两次。
#include<iostream>
#include<cstdio>
#include<cstring>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;
const int N = 10000;
const int INF = 999999999;
struct Edge{
    int v,w,next;
}edge[N*N];
int head[N];
int p[N],s[N],e[N];
int level[N];
int tot,n,m;
void init()
{
    memset(head,-1,sizeof(head));
    tot=0;
}
void addEdge(int u,int v,int w,int &k)
{
    edge[k].v = v,edge[k].w=w,edge[k].next=head[u],head[u]=k++;
    edge[k].v = u,edge[k].w=0,edge[k].next=head[v],head[v]=k++;
}
int BFS(int src,int des)
{
    queue<int>q;
    memset(level,0,sizeof(level));
    level[src]=1;
    q.push(src);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        if(u==des) return 1;
        for(int k = head[u]; k!=-1; k=edge[k].next)
        {
            int v = edge[k].v;
            int w = edge[k].w;
            if(level[v]==0&&w!=0)
            {
                level[v]=level[u]+1;
                q.push(v);
            }
        }
    }
    return -1;
}
int dfs(int u,int des,int increaseRoad){
    if(u==des||increaseRoad==0) return increaseRoad;
    int ret=0;
    for(int k=head[u];k!=-1;k=edge[k].next){
        int v = edge[k].v,w=edge[k].w;
        if(level[v]==level[u]+1&&w!=0){
            int MIN = min(increaseRoad-ret,w);
            w = dfs(v,des,MIN);
            if(w > 0)
            {
                edge[k].w -=w;
                edge[k^1].w+=w;
                ret+=w;
                if(ret==increaseRoad) return ret;
            }
            else level[v] = -1;
            if(increaseRoad==0) break;
        }
    }
    if(ret==0) level[u]=-1;
    return ret;
}
int Dinic(int src,int des)
{
    int ans = 0;
    while(BFS(src,des)!=-1) ans+=dfs(src,des,INF);
    return ans;
}
int main()
{
    int tcase;
    scanf("%d",&tcase);
    int t = 1;
    while(tcase--){
        init();
        scanf("%d%d",&n,&m);
        int MIN = INF,MAX = -1,sum = 0;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&p[i],&s[i],&e[i]);
            MIN = min(s[i],MIN);
            MAX = max(e[i],MAX);
            sum+=p[i];
        }
        int start = 0,ed = n+(MAX-MIN+1)+m+1;
        for(int i=1;i<=n;i++){
            addEdge(start,i,p[i],tot);
        }
        for(int i=1;i<=n;i++){
            for(int j=s[i]+n;j<=e[i]+n;j++){
                addEdge(i,j,1,tot);
            }
        }
        for(int i=MIN+n;i<=MAX+n;i++){
            for(int j=n+MAX-MIN+1+1;j<ed;j++){
                addEdge(i,j,1,tot);
            }
        }
        for(int i=n+MAX-MIN+1+1;i<ed;i++){
            addEdge(i,ed,INF,tot);
        }
        int max_flow = Dinic(start,ed);
        printf("Case %d: ",t++);
        if(max_flow==sum){
            printf("Yes\n");
        }else{
            printf("No\n");
        }
        printf("\n");
    }
    return 0;
}

 

posted @ 2016-07-30 09:54  樱花庄的龙之介大人  阅读(191)  评论(0编辑  收藏  举报