您的位置:首页 > 其它

Hdu 3572 Task Schedule [最大流] 任务分配,判断满流

2012-09-04 23:48 302 查看
题目意思:

给出 N 件任务和 M台机器, 这N件任务都一个限制: 必须在 [S,E] 之间完成, 而且完成的时间不能超过 P.

一台机器每天只能做意见任务, 不过庆幸的是: 任务是可以拆分的, 比如一件任务要3天完成, 那么你就可以将呀拆分

成3份. 现在问: 在所有机器慢负荷运转的情况下, 如何分配这些任务使得在最后的期限时, 所有任务都能完成.

解题 :

仔细分析下题目不难想到是个网络流模型, 问题就是求源点的流是否能够全部流到汇点. 关键在于构图. 我们选取一个

超级源点和一个超级汇点, 一开始把源点指向所有的任务, 边权就是完成这件任务需要的天数, 然后按照完成这件任务

的时间区间, 将任务分成 E-S+1份, 意思就是在这几天中每天都可以完成这件任务的一份.这样, 就可以在任务和能够完

成它的这些天之间连边, 边权为1, 因为每次只能做一份, 最后在所有的天和汇点之间连边, 边权为M, 表示每一天, M台

机器可以完成M份工作:





#include<iostream>
#include<cmath>
#include<cstring> 
using namespace std;   
#define MAXN 500 
#define MAXE 500002 
#define INF 0x7ffffff      
int ne,nv,tmp,s,t,index;  
struct Edge{ 
    int next,pair; 
    int v,cap,fLow; 
}edge[MAXE];
int net[MAXN];
int maxday; 
int ISAP() 
{ 
	int numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN]; 
 
    int cur_fLow,max_fLow,u,tmp,neck,i; 
    memset(dist,0,sizeof(dist)); 
    memset(numb,0,sizeof(numb)); 
    memset(pre,-1,sizeof(pre)); 
    for(i = 1 ; i <= nv ; ++i) 
        curedge[i] = net[i]; 
    numb[nv] = nv; 
    max_fLow = 0; 
    u = s; 
    while(dist[s] < nv) 
    { 
        if(u == t) 
        { 
            cur_fLow = INF; 
            for(i = s; i != t;i = edge[curedge[i]].v)  
            {   
                if(cur_fLow > edge[curedge[i]].cap) 
                { 
                    neck = i; 
                    cur_fLow = edge[curedge[i]].cap; 
                } 
            } 
            for(i = s; i != t; i = edge[curedge[i]].v) 
            { 
                tmp = curedge[i]; 
                edge[tmp].cap -= cur_fLow; 
                edge[tmp].fLow += cur_fLow; 
                tmp = edge[tmp].pair; 
                edge[tmp].cap += cur_fLow; 
                edge[tmp].fLow -= cur_fLow; 
            } 
            max_fLow += cur_fLow; 
            u = neck; 
        } 
        /* if .... eLse ... */
        for(i = curedge[u]; i != -1; i = edge[i].next) 
            if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1) 
                break; 
        if(i != -1) 
        { 
            curedge[u] = i; 
            pre[edge[i].v] = u; 
            u = edge[i].v; 
        }else{ 
            if(0 == --numb[dist[u]]) break; 
            curedge[u] = net[u]; 
            for(tmp = nv,i = net[u]; i != -1; i = edge[i].next) 
                if(edge[i].cap > 0) 
                    tmp = tmp<dist[edge[i].v]?tmp:dist[edge[i].v]; 
            dist[u] = tmp + 1; 
            ++numb[dist[u]]; 
            if(u != s) u = pre[u]; 
        } 
    }      
    return max_fLow; 
}
void addedge(int u,int v,int f)
{
	edge[index].next = net[u]; 
    edge[index].v = v; 
    edge[index].cap = f; 
    edge[index].fLow = 0; 
    edge[index].pair = index+1; 
    net[u] = index++; 
    edge[index].next = net[v]; 
    edge[index].v = u; 
    edge[index].cap = 0; 
    edge[index].fLow = 0; 
    edge[index].pair = index-1; 
    net[v] = index++;
	
} 
int main() 
{ 
    int i,j,np,nc,m,n; 
    int a,b,d,k,vaL;
	int tt;
	scanf("%d",&tt);
	for(int cas=1;cas<=tt;++cas)
	{ 
		int cases=1;
		int maxval=0;
		maxday=0;
		scanf("%d%d",&n,&m);  
		index=0;//index从0开始扫 
        s = 0; 
        t = 0;  
        memset(net,-1,sizeof(net));        
		for(i=1;i<=n;i++)
		{
			int pi,si,ei;
			scanf("%d%d%d",&pi,&si,&ei);
			maxday=max(maxday,ei);
			maxval+=pi;
			addedge(s,i,pi);
			for(j=si;j<=ei;j++)
				addedge(i,n+j,1);
			
			 
		}
		t=n+maxday+1;
		nv=t+1;
		for(i=1;i<=maxday;i++)
		addedge(i+n,t,m);		
		int ans=ISAP();
		if (ans == maxval)  
            printf("Case %d: Yes\n\n", cas);  
        else printf("Case %d: No\n\n", cas);  

    } 
    return 0; 
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: