题:https://ac.nowcoder.com/acm/contest/5278/L
题意:给定n个种类的事件以及每天最多做的事件次数m,每种事件都会在一周的某一天内发生且要求完成一定的次数,问最少多少天能完成?
分析:答案具有单调性,所以二分考虑,问题就变为每次二分能否达成全部完成,达成性条件我们可以考虑网络流,具体连线如下:

#include<bits/stdc++.h> using namespace std; const int M=4e5+5; const int N=2e3+3; const int inf=0x3f3f3f3f; int tot,s,t; struct node{ int u,v,nextt; int w; }e[M<<1]; vector<node>g[M]; int head[N],deep[N],cur[N],sign[N][8],need[N]; void addedge(int u,int v,int w){ e[tot].v=v; e[tot].w=w; e[tot].nextt=head[u]; head[u]=tot++; e[tot].v=u; e[tot].w=0; e[tot].nextt=head[v]; head[v]=tot++; } bool bfs(){ for(int i=0;i<=t;i++) deep[i]=0; queue<int>que; que.push(s); deep[s]=1; while(!que.empty()){ int u=que.front(); que.pop(); for(int i=head[u];~i;i=e[i].nextt){ int v=e[i].v; if(e[i].w>0&&deep[v]==0){ deep[v]=deep[u]+1; if(v==t) return true; que.push(v); } } } return deep[t]!=0; } int dfs(int u,int fl){ if(u==t) return fl; int ans=0,x=0; for(int i=cur[u];~i;i=e[i].nextt){ int v=e[i].v; if(e[i].w>0&&deep[v]==deep[u]+1){ x=dfs(v,min(fl-ans,e[i].w)); e[i].w-=x; e[i^1].w+=x; ans+=x; if(ans==fl) return ans; if(e[i].w) cur[u]=i; } } if(ans==0) deep[u]=0; return ans; } int dinic(){ int res=0; while(bfs()){ for(int i=0;i<=t;i++) cur[i]=head[i]; res+=dfs(s,inf); } return res; } int n,m,sum=0; bool check(int x){ if(x*m<sum) return false; s=0,t=n+7+1; for(int i=0;i<=t+1;i++) head[i]=-1; tot=0; int now=0; for(int i=1;i<=7;i++) addedge(s,++now,m*(x/7+(x%7>=i))); for(int i=1;i<=n;i++){ now++; addedge(now,t,need[i]); for(int j=1;j<=7;j++) if(sign[i][j]) addedge(j,now,inf); } return dinic()==sum; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&need[i]); sum+=need[i]; int q; scanf("%d",&q); while(q--){ int x; scanf("%d",&x); sign[i][x]=1; } } int l=0,r=1e9/m,ans; while(l<=r){ int x=(l+r)>>1; if(check(x)) ans=x,r=x-1; else l=x+1; } printf("%d ",ans); return 0; }