题意:
有N个事件,M台机器。事件有开始时间,持续时间,要在结束时间之前完成,问是否能完成所有事件?
非自己思考出来的
建图:把每个任务和每一天都看做一个点,添加源点和汇点。源点与每个任务之间连一条边,容量为完成该任务所需处理次数。若第i个任务可以在Si至Ei天处理,则由该任务向这些天分别连一条边,容量为1,表示此任务每天只能被处理一次。最后,从每一天连一条到汇点的边,容量为机器数M,表示每天可以处理M个任务。若求出的最大流等于所有任务需要处理的次数之和,说明能完成任务;否则,不能完成任务。
#include#include #include #include #include #include #include #include #include #define oo 0x13131313using namespace std;int N,M;using namespace std;const int MAXN=5000+5;const int MAXM=300000+5;const int INF=0x3f3f3f3f;const int TT=500+500+2;const int S=0;struct Edge{ int to,next,cap,flow; void get(int a,int b,int c,int d) { to=a;next=b;cap=c;flow=d; }}edge[MAXM];int tol;int head[MAXN];int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];void init(){ tol=0; memset(head,-1,sizeof(head));}//单向图三个参数,无向图四个参数void addedge(int u,int v,int w,int rw=0){ edge[tol].get(v,head[u],w,0);head[u]=tol++; edge[tol].get(u,head[v],rw,0);head[v]=tol++;}int sap(int start,int end,int N){ memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memcpy(cur,head,sizeof(head)); int u=start; pre[u]=-1; gap[0]=N; int ans=0; while(dep[start] edge[i].cap-edge[i].flow) Min=edge[i].cap-edge[i].flow; for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]) { edge[i].flow+=Min; edge[i^1].flow-=Min; } u = start; ans+=Min; continue; } bool flag=false; int v; for(int i=cur[u];i !=-1;i=edge[i].next) { v=edge[i].to; if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]) { flag=true; cur[u]=pre[v]=i; break; } } if(flag) { u=v; continue; } int Min=N; for(int i=head[u];i!=-1;i=edge[i].next) if(edge[i].cap-edge[i].flow&&dep[edge[i].to] >N>>M; for(int i=1;i<=N;i++) { scanf("%d%d%d",&p,&s,&e); sum+=p; addedge(S,i,p); //源点到任务连一条流量为p的边 for(int j=s;j<=e;j++) { addedge(i,N+j,1); //任务到s-e间连一条流量为1的边 } } for(int i=1;i<=500;i++) { addedge(N+i,TT,M); //时间到汇点连一条流量为M的边,表示一天最多处理的事情 }}int main(){ // File(); int T; cin>>T; int CASE=0; while(T--) { printf("Case %d: ",++CASE); init(); input(); if(sum==sap(S,TT,1003)) cout<<"Yes"<