最大流任务调度——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(""); } }