HDU 3572 Task Schedule 建图+sap模板

点击打开链接

 

 

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

折磨了我一晚上,终于弄出来了,题意是:用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:a
using 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);
		else
		printf("Case %d: No\n\n",cas);
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值