最大流任务调度——hdu3572二分图建图

很简单的任务调度模板题

把一个工作完成一天的量当做是边

/*
任务调度问题最大流 
因为两个任务之间是没有关系的,两天之间也是没有关系的
所以抽象成二分图
任务i在天数[si,ei]之间都连一条双向边,权值为1,表示一天一个任务最多只能完成一个任务点 
建立超级源点s,和所有的任务连双向边,权值为pi,表示需要pi天来完成任务
建立超级汇点t,和所有的天数连双向边,权值为m,表示这一天最多完成的任务贡献点
如果最大流是sum{pi} 就是可行,反之不行 
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
#define inf 0x3f3f3f3f
struct Task{int s,e,p;}u[maxn];
struct Edge{int to,nxt,w;}e[maxn<<1];
int head[maxn],T,tot,n,m,w,N,M,s,t;
void init(){memset(head,-1,sizeof head);tot=0;}
void add(int u,int v,int w){
    e[tot].to=v;e[tot].w=w;e[tot].nxt=head[u];head[u]=tot++;
}

int d[maxn];
bool bfs(){//在残量网络上构造分层图 
    memset(d,0,sizeof d);
    
    queue<int>q;
    while(q.size())q.pop();
    q.push(s);d[s]=1;
    
    while(q.size()){
        int x=q.front();q.pop();
        for(int i=head[x];i!=-1;i=e[i].nxt){
            int y=e[i].to;
            if(d[y] || e[i].w==0)continue;
            q.push(y);
            d[y]=d[x]+1;
            if(y==t)return 1;
        }
    }
    return 0;
}
int dinic(int x,int flow){
    if (x==t)return flow;
    int rest=flow;
    for(int i=head[x];i!=-1 && rest>0;i=e[i].nxt){
        int y=e[i].to;
        if(e[i].w==0 || d[y]!=d[x]+1)continue;
        int k=dinic(y,min(rest,e[i].w));
        if(!k)    d[y]=0;    //y点已经被增广完毕,本次dinic时不会再访问这个点
        e[i].w-=k; e[i^1].w+=k;
        rest-=k;
    }
    return flow-rest;
} 

int main(){
    cin>>T;
    for(int tt=1;tt<=T;tt++){
        init();
        cin>>N>>M;
        int Max=0,sum=0;//最晚完成的天数 
        for(int i=1;i<=N;i++){
            cin>>u[i].p>>u[i].s>>u[i].e;
            Max=max(Max,u[i].e); 
            sum+=u[i].p;
        }
        
        //建图 
        n=Max+N;//点数
        for(int i=1;i<=N;i++){
            for(int j=u[i].s;j<=u[i].e;j++){
                add(i,j+N,1);add(j+N,i,0);
            }
        }
        s=n+1;t=n+2;
        for(int i=1;i<=N;i++){
            add(s,i,u[i].p);add(i,s,0);
        }
        for(int i=N+1;i<=n;i++){ 
            add(i,t,M);add(t,i,0);
        } 
        
        int flow=0,ans=0;
        while(bfs())
            while(flow=dinic(s,inf))
                ans+=flow;
        if(ans==sum)
            printf("Case %d: Yes\n",tt);
        else printf("Case %d: No\n",tt);
        puts("");
    }
}

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/10988606.html