HDU 3572 Task Schedule

39 篇文章 0 订阅
38 篇文章 0 订阅
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 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

最大流(dinic)+(神奇的)构图~

这道题用Edmonds-Karp会T得很惨,一定要用dinic,而且还要用邻接表存储,尽量卡常。


T了的Edmonds-Karp

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;

int T,n,m,P[501],S[510],E[510],cnt,a[1005],ne[1005],ans,tot,totans;

struct edge{
	int x,y,cap,flow;
	edge(int u,int v,int k,int z):x(u),y(v),cap(k),flow(z) {}
};

vector<edge> ed;
vector<int> p[1005];

void add(int u,int v,int k)
{
	ed.push_back(edge(u,v,k,0));
	ed.push_back(edge(v,u,0,0));
	int totnunmtot=ed.size();
	p[u].push_back(totnunmtot-2);
	p[v].push_back(totnunmtot-1);
}

int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);ans=tot=totans=0;ed.clear();
		for(int i=1;i<=n;i++) p[i].clear();
		for(int i=1;i<=n;i++)
		{
			scanf("%d%d%d",&P[i],&S[i],&E[i]);  //Si以后开始做,在Ei之前完成,Pi 个时间单位 
			add(0,i,1);totans+=P[i];
			for(int j=S[i];j<=E[i];j++) add(i,j+n,P[i]);
			tot=max(tot,E[i]);
		}
		for(int i=1;i<=tot;i++) add(i+n,tot+n+1,m);tot+=n+1;
		while(1)
		{
			memset(a,0,sizeof(a));
			queue<int> q;q.push(1);
			a[0]=999999999;
			while(!q.empty())
			{
				int k=q.front();q.pop();
				int totnum=p[k].size();
				for(int i=0;i<totnum;i++)
				{
					edge z=ed[p[k][i]];
					if(!a[z.y] && z.cap>z.flow)
					{
						ne[z.y]=p[k][i];q.push(z.y);
						a[z.y]=min(a[k],z.cap-z.flow);
					}
				}
				if(a[tot]) break;
			}
			if(!a[tot]) break;
			for(int i=tot;i;i=ed[ne[i]].x)
			{
				ed[ne[i]].flow+=a[tot];
				ed[ne[i]^1].flow-=a[tot];
			}
			ans+=a[tot];
		}
		if(ans==totans) printf("Case %d: Yes\n\n",++cnt);
		else printf("Case %d: No\n\n",++cnt);
	}
	return 0;
}


A了的dinic:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;

int t,n,m,p[502],s[502],e[502],cnttt,cnt,ans,tot,totans,a[1002][1002],dis[1002],now;
int minn,maxx,fi[1002],ne[1000001],w[1000001],v[1000001];

void add(int u,int vv,int val)
{
	w[cnt]=vv;ne[cnt]=fi[u];v[cnt]=val;fi[u]=cnt++;
	w[cnt]=u;ne[cnt]=fi[vv];v[cnt]=0;fi[vv]=cnt++;
}

bool bfs()
{
	memset(dis,0,sizeof(dis));
	queue<int> q;q.push(0);dis[0]=1;
	while(!q.empty())
	{
		int k=q.front();q.pop();
		for(int i=fi[k];i!=-1;i=ne[i])
		  if(v[i] && !dis[w[i]])
		  {
		  	dis[w[i]]=dis[k]+1;
		  	if(w[i]==tot) return 1;
			q.push(w[i]);
		  }
	}
	return 0;
}

int dfs(int u,int vv)
{
	if(u==tot) return vv;
	int kkz,cost=0;
	for(int i=fi[u];i!=-1;i=ne[i])
	  if(v[i] && dis[w[i]]==dis[u]+1)
	  {
	  	kkz=dfs(w[i],min(v[i],vv-cost));
	  	if(kkz>0)
	  	{
	  		v[i]-=kkz;v[i^1]+=kkz;cost+=kkz;
		  	if(cost==vv) break;
		}
		else dis[w[i]]=-1;
	  }
	return cost;
}

int main()
{
	scanf("%d",&t);
	while(t--)
	{
		memset(fi,-1,sizeof(fi));
		scanf("%d%d",&n,&m);ans=totans=maxx=cnt=0;minn=1001;
		for(int i=1;i<=n;i++)
		{
			scanf("%d%d%d",&p[i],&s[i],&e[i]);
			totans+=p[i];maxx=max(maxx,e[i]);minn=min(minn,s[i]);
		}
		for(int i=minn;i<=maxx;i++) add(0,i,m);tot=maxx*2;
		for(int i=1;i<=n;i++)
		  for(int j=s[i];j<=e[i];j++) add(j,j+maxx,1),add(j+maxx,tot,1);
		while(bfs()) ans+=dfs(0,999999999);
		if(ans>=totans) printf("Case %d: Yes\n\n",++cnttt);
		else printf("Case %d: No\n\n",++cnttt);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值