首先观察到答案具有单调性,可以二分答案判断。
至于判断方式,可以采用是否符合满流判断是否可以达到目的。
#include<bits/stdc++.h> #define int long long using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<ll,ll> pll; const int N=2e6+10; const int M=2e6+10; const int inf=0x3f3f3f3f; int n,E; ll h[N],ne[N],e[N]; ll f[N],idx; int c[N]; int a[8][N],m; ll sum; int S,T; int d[N],cur[N]; void add(int a,int b,int c){ e[idx]=b,ne[idx]=h[a],f[idx]=c,h[a]=idx++; e[idx]=a,ne[idx]=h[b],f[idx]=0,h[b]=idx++; } int bfs(){ memset(d,-1,sizeof d); d[S]=0; cur[S]=h[S]; queue<int> q; q.push(S); while(q.size()){ int t=q.front(); q.pop(); for(int i=h[t];i!=-1;i=ne[i]){ int j=e[i]; if(d[j]==-1&&f[i]){ cur[j]=h[j]; d[j]=d[t]+1; if(j==T) return true; q.push(j); } } } return false; } int find(int u,int limit){ if(u==T){ return limit; } int i; int flow=0; for(i=cur[u];i!=-1&&flow<limit;i=ne[i]){ cur[u]=i; int j=e[i]; if(d[j]==d[u]+1&&f[i]){ int t=find(j,min(f[i],limit-flow)); if(!t) d[j]=-1; else{ f[i]-=t; f[i^1]+=t; flow+=t; } } } return flow; } int dinic(){ int flow; int r=0; while(bfs()){ while(flow=find(S,inf)) r+=flow; } return r; } bool check(int x){ S=0,T=7+n+1; idx=0; memset(h,-1,sizeof h); for (int i = 1; i <= 7; ++i){ add(S,i,1ll*E*(x/7+(x%7>=i))); } for (int i=1;i<=n;++i) { for (int j=1;j<=7;++j){ if(a[j][i]) add(j,i+7,inf); } add(i+7,T,c[i]); } return dinic() >= sum; } signed main(){ ios::sync_with_stdio(false); cin>>n>>E; memset(h,-1,sizeof h); int i; for(i=1;i<=n;i++){ cin>>c[i]>>m; int j; sum+=c[i]; for(j=1;j<=m;j++){ int x; cin>>x; a[x][i]=1; } } int l=0,r=1e12; while(l<r){ int mid=l+r>>1; if(check(mid)){ r=mid; } else l=mid+1; } cout<<l<<endl; }