题目链接:
https://www.luogu.com.cn/problem/P2754
思路参考博客:
1:https://www.luogu.com.cn/blog/AH2002/solution-p2754
2:https://www.luogu.com.cn/blog/Qiu/solution-p2754
算法:1:分层图
图解:
思路:
1:每一层代表的是每一天的空间站和地球,月亮的状态
2:枚举天数,如果截至这天的逃离人数已经大于等于了题目要求逃离的人数,那么直接输出答案。如果天数到了第27天,还是没有一个人可以登月,那么就说明,不可能逃离了(无解),因为由计算可以得,27天时,至少有一个人可以逃到月亮上去,如果第27天时,最大流还是0,说明无解
3:连边,跑最大流,dinic利用残量网络可以跑得更快
代码:
#include <bits/stdc++.h>
//Dinic+当前弧优化
using namespace std;
const int maxn=2e4+2e2+5e1,maxm=9e4+4e3+5e2+1,inf=0x7fffffff;
int n,m,k,s,t,tot=1,head[maxn],cur[maxn],dep[maxn],a[21],b,ans,cnt,cycle[21][16],p[21];//用上了分层图,可以用dep判重了
struct edge
{
int to,next,w;
}e[maxm];
void addedge(int x,int y,int w)
{
e[++tot].to=y;e[tot].w=w;e[tot].next=head[x];head[x]=tot;
e[++tot].to=x;e[tot].w=0;e[tot].next=head[y];head[y]=tot;
}
bool bfs()//bool 函数是一个小优化,判断是否能搜到汇点,如果连汇点都搜不到还dfs干什么?
{
memset(dep,0,sizeof dep);//一定要初始化
memcpy(cur,head,sizeof(head));
queue<int>q;
q.push(s);dep[s]=1;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].to,w=e[i].w;
if(w&&!dep[y])//如果有残余流量(没有的话谁也过不去)并且这个点是第一次到达
{
dep[y]=dep[x]+1;
q.push(y);
}
}
}
return dep[t];//t 的深度不为0,就是搜到了汇点
}
int dfs(int u,int flow) {
if(u==t) return flow;
int ans=0;
for(int i=cur[u];i&&ans<flow;i=e[i].next) {
cur[u]=i;
int v=e[i].to;
if(e[i].w&&dep[v]==dep[u]+1) {
int x=dfs(v,min(e[i].w,flow-ans));
if(x) e[i].w-=x,e[i^1].w+=x,ans+=x;
}
}
if(ans<flow) dep[u]=-1;//说明这个点已经榨干
return ans;
}
int main()
{
ios::sync_with_stdio(0);
scanf("%d %d %d",&n,&m,&k);
s=0,t=n+1,cnt=t;
int g=n+2;
for(int i=1;i<=m;i++)
{
scanf("%d %d",&p[i],&a[i]);
for(int j=0;j<a[i];j++)
{
scanf("%d",&b);
// if(b!=-1)cycle[i][j]=b;
// else cycle[i][j]=t;
cycle[i][j]=(b!=-1?b:t);
}
}
int day=0;
while(true)
{
if(day==27&&ans==0)
{
printf("%d\n",ans);
break;
}
for(int i=0;i<=n;i++)
{
++cnt;addedge(cnt-g,cnt,inf);
}
++cnt;addedge(cnt,cnt-g,inf);
for(int i=1;i<=m;i++)
{
addedge(cycle[i][day%a[i]]+day*g,cycle[i][(day+1)%a[i]]+(day+1)*g,p[i]);
}
++day;
while(bfs())ans+=dfs(s,inf);
if(ans>=k)
{
printf("%d\n",day);
break;
}
}
return 0;
}