HDU 3572 Task Schedule 建图+sap模板

来源:互联网 发布:清空文件夹内容 linux 编辑:程序博客网 时间:2024/06/11 22:39

点击打开链接

 

 

Task Schedule

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


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
24 31 3 5 1 1 42 3 73 5 92 22 1 31 2 2
 


 

Sample Output
Case 1: Yes Case 2: Yes
 


 

Author
allenlowesy
 


 

Source
2010 ACM-ICPC Multi-University Training Contest(13)——Host by UESTC
 


 

Recommend
zhouzeyong
 

折磨了我一晚上,终于弄出来了,题意是:用m个机器处理n个任务,每个任务必须在[s,e]这段时间内完成,且需要p天。每个机器只能处理一个任务,每天能处理m个任务。此题最大难点,我认为是如何建图,来求最大流。把每个任务看成一个点,然后跟源点相连,容量即为完成该任务的时间,即p。若i任务的时间是在s到e天,则将该任务向这些天数各增加一条边,容量为1,因为一天只能一台机器工作。最后从每一天连一条到汇点的边,容量为机器数m。因为一天能够处理m个任务。至此,建图完成。只需求出最大流和所以任务需要处理的天数进行比较即可。真是完美的建图。一开始我是用EK算法做的,但是结果意料之中的TLE,果然这个算法比较慢。然后改为SAP,错了几次后AC。对于SAP算法的具体思想还不是很理解,所以果断套的模板。

好了,该洗洗睡了。

//SAP算法#include<stdio.h>#include<string.h>#define inf 9999999#define MIN(a,b) a>b?b:a;struct E{    int v,w,next;    E(){}    E(int v,int w,int next):v(v),w(w),next(next){}}edg[500000];int dis[2000],gap[2000],list[2000],nodes;int sourse,sink,nn,node;void addedge(int u,int v,int w){    edg[nodes]=E(v,w,list[u]);    list[u]=nodes++;    edg[nodes]=E(u,0,list[v]);    list[v]=nodes++;}int dfs(int src,int aug){    if(src==sink)return aug;    int left=aug,mindis=nn;    for(int j=list[src];j!=-1;j=edg[j].next)    {    int v=edg[j].v;    if(edg[j].w)        {           if(dis[v]+1==dis[src])           {               int minn=MIN(left,edg[j].w);               minn=dfs(v,minn);               edg[j].w-=minn;               edg[j^1].w+=minn;               left-=minn;               if(dis[sourse]>=nn)return aug-left;               if(left==0)break;           }           if(dis[v]<mindis)           mindis=dis[v];        }    }        if(left==aug)        {            if(!(--gap[dis[src]]))dis[sourse]=nn;            dis[src]=mindis+1;            gap[dis[src]]++;        }        return aug-left;}int sap(int s,int e){    int ans=0;nn=e+1;    memset(dis,0,sizeof(dis));    memset(gap,0,sizeof(gap));    gap[0]=nn;    sourse=s;    sink=e;    while(dis[sourse]<nn)    ans+=dfs(sourse,inf);    return ans;}int main(){    int cas,e;    scanf("%d",&cas);    for(int k=1;k<=cas;k++)    {        memset(list,-1,sizeof(list));        nodes=0;        int n,m,p,s=0,sum=0,maxx=0;        sourse=0;        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++){scanf("%d%d%d",&p,&s,&e);sum+=p;maxx=maxx>e?maxx:e;addedge(0,i,p);for(int j=s;j<=e;j++){addedge(i,j+n,1);}}e=n+maxx+1;for(int i=1;i<=maxx;i++)addedge(n+i,e,m);  int anss=sap(0,e);  if(anss==sum)        printf("Case %d: Yes\n\n",k);        else        printf("Case %d: No\n\n",k);    }    return 0;}


 

 

//TLE的EK算法 #include<stdio.h>#include<queue>#include<algorithm>#define inf 9999999#define MIN(a,b) a>b?b:ausing namespace std;int map[1007][1007],flow[1007][1007],p[1007],a[1007];int EK(int s,int t,int n){int sum=0;queue<int>q;memset(flow,0,sizeof(flow));for(;;){memset(a,0,sizeof(a));a[s]=inf;q.push(s);while(!q.empty()){int u=q.front();q.pop();for(int i=1;i<=n;i++){if(!a[i]&&map[u][i]>flow[u][i]){p[i]=u;q.push(i);a[i]=MIN(a[u],map[u][i]-flow[u][i]);}}}if(!a[t])break;for(int i=t;i!=s;i=p[i]){flow[p[i]][i]+=a[t];flow[i][p[i]]-=a[t];}sum+=a[t];}return sum;}int main(){int t,sink,vn;scanf("%d",&t);for(int cas=1;cas<=t;cas++){int n,m;int p,s,e,sum=0,maxx=0,sourse=0;memset(map,0,sizeof(map));scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d%d%d",&p,&s,&e);sum+=p;maxx=maxx>e?maxx:e;map[sourse][i]+=p;for(int j=s;j<=e;j++){map[i][n+j]+=1;}}sink=n+maxx+1;vn=sink+1;for(int i=1;i<=maxx;i++)map[n+i][sink]+=m;if(EK(sourse,sink,vn)==sum)printf("Case %d: Yes\n\n",cas);elseprintf("Case %d: No\n\n",cas);}return 0;}


 

原创粉丝点击