题解:利用分层图思想加入时间概念,第0天地球编号设为0,月球编号设为n+1,空间站编号在1到n之间。对于每一天都新建n+2个点表示不同天不同地方的情况,这样加入了时间概念。源点与第0天的地球建立一条容量k的边表示初始所有人在地球上,不同点与上一天相同点建立一条容量正无穷的边表示任意地方可以容纳无限多的人,每一天的月球与汇点建立一条正无穷的点,因为本题只加边所以可在上一天的残余网络上增广,直到汇点的容量大于等于k位置。判断无法到达用并查集判断即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=760,M=(2*N+1e3)*2,inf=1e9; 4 int h[N],e[M],ne[M],f[M],idx; 5 int d[N],cur[N],p[30]; 6 int n,m,k,S,T; 7 struct node 8 { 9 int sum,r,id[30]; 10 }ship[30]; 11 int find(int x) 12 { 13 if(p[x]!=x)p[x]=find(p[x]); 14 return p[x]; 15 } 16 int get(int day,int u) 17 { 18 return day*(n+2)+u; 19 } 20 void add(int a,int b,int c) 21 { 22 ne[idx]=h[a],e[idx]=b,f[idx]=c,h[a]=idx++; 23 ne[idx]=h[b],e[idx]=a,f[idx]=0,h[b]=idx++; 24 } 25 bool bfs() 26 { 27 memset(d,-1,sizeof d); 28 queue<int>q; 29 q.push(S); 30 cur[S]=h[S]; 31 d[S]=0; 32 while(q.size()) 33 { 34 int t=q.front(); 35 q.pop(); 36 for(int i=h[t];i!=-1;i=ne[i]) 37 { 38 int j=e[i]; 39 if(d[j]==-1&&f[i]) 40 { 41 d[j]=d[t]+1; 42 cur[j]=h[j]; 43 if(j==T)return true; 44 q.push(j); 45 } 46 } 47 } 48 return false; 49 } 50 int find(int u,int limit) 51 { 52 if(u==T)return limit; 53 int flow=0; 54 for(int i=cur[u];i!=-1&&flow<limit;i=ne[i]) 55 { 56 int j=e[i]; 57 cur[u]=i; 58 if(d[j]==d[u]+1&&f[i]) 59 { 60 int t=find(j,min(f[i],limit-flow)); 61 if(!t)d[j]=-1; 62 f[i]-=t,f[i^1]+=t,flow+=t; 63 } 64 } 65 return flow; 66 } 67 int dinic() 68 { 69 int r=0,flow; 70 while(bfs())while(flow=find(S,inf))r+=flow; 71 return r; 72 } 73 int main() 74 { 75 memset(h,-1,sizeof h); 76 cin>>n>>m>>k; 77 S=N-1,T=N-2; 78 for(int i=0;i<=n+1;i++)p[i]=i; 79 for(int i=0;i<m;i++) 80 { 81 int x,y; 82 scanf("%d%d",&x,&y); 83 ship[i].sum=x; 84 ship[i].r=y; 85 for(int j=0;j<y;j++) 86 { 87 int id; 88 scanf("%d",&id); 89 if(id==-1)id=n+1; 90 ship[i].id[j]=id; 91 if(j) 92 { 93 int de=ship[i].id[j-1]; 94 p[find(de)]=find(id); 95 } 96 } 97 } 98 if(find(0)!=find(n+1))puts("0"); 99 else 100 { 101 add(S,get(0,0),k); 102 add(get(0,n+1),T,inf); 103 int res=0,day=1; 104 while(1) 105 { 106 for(int i=0;i<=n+1;i++) 107 add(get(day-1,i),get(day,i),inf); 108 add(get(day,n+1),T,inf); 109 for(int i=0;i<m;i++) 110 { 111 int r=ship[i].r; 112 int x=get(day-1,ship[i].id[(day-1)%r]); 113 int y=get(day,ship[i].id[day%r]); 114 add(x,y,ship[i].sum); 115 } 116 res+=dinic(); 117 if(res>=k)break; 118 day++; 119 } 120 printf("%d ",day); 121 } 122 }