一开始以为跑费用流,后来看了题解才知道可以按天建图。
1.从源点向每一天的地球链接一条INF
2.从每一天的月亮向汇点链接一条INF
3.从上一天的每一个节点向当天的对应节点链接一条INF(因为人们可以留在中转站等一等嘛)
4.针对每一艘飞船,获取其上一天的位置,再获取这一天的位置,在这两个点之间连一条容量为飞船满载人数的流
每次新加一天然后跑到最大流超过k即可
至于无解的情况只要当ans达到一个很大的值的时候跳出来即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10,inf=1e9; 4 int head[N],cnt=-1,v[N],h[N],p[N],n,m,k,s,t,day[25][25]; 5 queue<int>q; 6 struct node{ 7 int to,nex,w; 8 }e[N<<1]; 9 void add(int x,int y,int w) 10 { 11 e[++cnt].to=y;e[cnt].w=w;e[cnt].nex=head[x];head[x]=cnt; 12 e[++cnt].to=x;e[cnt].w=0;e[cnt].nex=head[y];head[y]=cnt; 13 } 14 bool bfs(int x,int y) 15 { 16 memset(v,-1,sizeof(v)); 17 v[x]=0;q.push(x); 18 while(!q.empty()) 19 { 20 int x=q.front();q.pop(); 21 for(int i=head[x];i!=-1;i=e[i].nex) 22 { 23 int y=e[i].to; 24 if(v[y]!=-1||!e[i].w)continue; 25 v[y]=v[x]+1;q.push(y); 26 } 27 } 28 return v[y]!=-1; 29 } 30 int dfs(int x,int w,int yy) 31 { 32 if(!w||x==yy)return w;int s=0; 33 for(int i=head[x];i!=-1;i=e[i].nex) 34 { 35 int y=e[i].to; 36 if(v[y]!=v[x]+1||!e[i].w)continue; 37 int flow=dfs(y,min(w-s,e[i].w),yy); 38 if(!flow){v[y]=-1;continue;} 39 s+=flow;e[i].w-=flow;e[i^1].w+=flow; 40 if(s==w)return s; 41 } 42 return s; 43 } 44 int dinic(int x,int y) 45 { 46 int tmp=0; 47 while(bfs(x,y)) 48 { 49 tmp+=dfs(x,inf,y); 50 } 51 return tmp; 52 } 53 int main() 54 { 55 scanf("%d%d%d",&n,&m,&k); 56 n+=2;memset(head,-1,sizeof(head)); 57 for(int i=1;i<=m;++i) 58 { 59 scanf("%d%d",&h[i],&p[i]); 60 for(int j=0;j<p[i];++j) 61 { 62 scanf("%d",&day[i][j]); 63 day[i][j]+=2; 64 } 65 } 66 s=10001,t=10000;int ans=0;int sum=0; 67 while(ans<=500) 68 { 69 add(s,ans*n+2,inf); 70 add(ans*n+1,t,inf); 71 if(ans) 72 { 73 for(int i=0;i<=n;++i) 74 add((ans-1)*n+i,ans*n+i,inf); 75 for(int i=1;i<=m;++i) 76 { 77 add((ans-1)*n+day[i][(ans-1)%p[i]],ans*n+day[i][ans%p[i]],h[i]); 78 } 79 } 80 sum+=dinic(s,t); 81 if(sum>=k) 82 { 83 printf("%d ",ans); 84 return 0; 85 } 86 ans++; 87 } 88 puts("0"); 89 return 0; 90 }