题目描述
由于人类对自然资源的消耗,人们意识到大约在 2300 年之后,地球就不能再居住了。于是在月球上建立了新的绿地,以便在需要时移民。令人意想不到的是,2177 年冬由于未知的原因,地球环境发生了连锁崩溃,人类必须在最短的时间内迁往月球。
现有 nn 个太空站位于地球与月球之间,且有 mm 艘公共交通太空船在其间来回穿梭。每个太空站可容纳无限多的人,而太空船的容量是有限的,第 ii 艘太空船只可容纳 h_ihi 个人。每艘太空船将周期性地停靠一系列的太空站,例如 (1,3,4)(1,3,4) 表示该太空船将周期性地停靠太空站 134134134\dots134134134…。每一艘太空船从一个太空站驶往任一太空站耗时均为 11。人们只能在太空船停靠太空站(或月球、地球)时上、下船。
初始时所有人全在地球上,太空船全在初始站。试设计一个算法,找出让所有人尽快地全部转移到月球上的运输方案。
输入格式
输入的第一行是三个用空格隔开的整数,分别代表太空站个数 nn,太空船个数 mm 和地球上的人数 kk。
第 22 到第 (m + 1)(m+1) 行,每行给出一艘太空船的信息,第 (i + 1)(i+1) 行的第一个整数 h_ihi 代表第 ii 艘太空船可容纳的人数。随后有一个整数 r_iri,代表第 ii 艘太空船停靠的站点数。之后有 r_iri 个整数,依次代表该太空船停靠站点的编号 S_{i, j}Si,j,其中太空站自 11 至 nn 编号,地球编号为 00,月球编号为 -1−1。
输出格式
输出一行一个整数,代表将所有人转移到月球上的最短用时。若无解则输出 00。
/* *从源点向每一天的地球连一条inf *从每一天的地球向汇点连一条inf *从上一天的每个节点向当天的对应节点连一条inf *针对每一艘飞船,上一天的位置和这一天的位置连一天边,容量为飞船的人数 *每次新加一天跑一遍Dinic,直到答案超过目标人数 */ #include<bits/stdc++.h> using namespace std; const int maxn=1e5+100; const int inf=1e9; int head[maxn]; struct node { int u,v,w,nxt; }edge[maxn]; int tot=0; void addedge (int u,int v,int w) { edge[tot].u=u; edge[tot].v=v; edge[tot].w=w; edge[tot].nxt=head[u]; head[u]=tot++; edge[tot].u=v; edge[tot].v=u; edge[tot].w=0; edge[tot].nxt=head[v]; head[v]=tot++; } int dep[maxn]; int inq[maxn]; int cur[maxn]; int wjm; int maxflow=0; int s,t; bool bfs () { for (int i=0;i<maxn;i++) { cur[i]=head[i]; dep[i]=inf; inq[i]=0; } dep[s]=0; queue<int> q; q.push(s); while (!q.empty()) { int u=q.front(); q.pop(); inq[u]=0; for (int i=head[u];i!=-1;i=edge[i].nxt) { int v=edge[i].v; if (dep[v]>dep[u]+1&&edge[i].w) { dep[v]=dep[u]+1; if (inq[v]==0) { q.push(v); inq[v]=1; } } } } if (dep[t]!=inf) return 1; return 0; } int dfs (int u,int flow) { int increase=0; if (u==t) { wjm=1; maxflow+=flow; return flow; } int used=0; for (int i=cur[u];i!=-1;i=edge[i].nxt) { cur[u]=i; int v=edge[i].v; if (edge[i].w&&dep[v]==dep[u]+1) { if (increase=dfs(v,min(flow-used,edge[i].w))) { used+=increase; edge[i].w-=increase; edge[i^1].w+=increase; if (used==flow) break; } } } return used; } int Dinic () { maxflow=0; while (bfs()) { wjm=1; while (wjm==1) { wjm=0; dfs(s,inf); } } return maxflow; } struct position { int h; int nxt[205]; int zq; }p[maxn]; int main () { for (int i=0;i<maxn;i++) head[i]=-1; int n,m,k; scanf("%d%d%d",&n,&m,&k); n+=2; for (int i=1;i<=m;i++) { scanf("%d%d",&p[i].h,&p[i].zq); for (int j=0;j<p[i].zq;j++) { scanf("%d",&p[i].nxt[j]); p[i].nxt[j]+=2; } } //0为源点,(ans-1)*(2+m)为地球, (ans-1)*(2+m)+i表示第ans天的第i个站,(ans)*(2+m)-1表示第i天的月球 s=0,t=1e5; int ans; int sum=0; while (ans<500) { addedge(ans*n+1,t,inf); addedge(s,ans*n+2,inf); if (ans) { for (int i=1;i<=n;i++) addedge((ans-1)*n+i,ans*n+i,inf); for (int i=1;i<=m;i++) { int x=p[i].nxt[(ans-1)%p[i].zq]; int y=p[i].nxt[(ans)%p[i].zq]; addedge((ans-1)*n+x,ans*n+y,p[i].h); } } sum+=Dinic(); if (sum>=k) break; ans++; } if (ans==500) printf("0\n"); else printf("%d\n",ans); return 0; }