题意
给定一张有向图,每条边每天最多经过有限次,一个人每天只能经过一条边, T 个人从1号点出发,问多少天之后能到达
n 点
解法
分层图+最大流:
一开始没有看见每一个人每天只能走一条边这个条件,所以就 WA 了很多次
对每一天建一层图,并且上下两层之间要联通,然后每一层的 n 号点也要和汇点联通,那么我们可以对这个分层图求最大流,如果最大流≥T ,显然经过的层数就是答案
为了方便,我们可以枚举天数,逐天进行加边,每加完一天的边就跑一次最大流,如果如何条件,即是答案,否则复原原图,继续下一天
复杂度
O( ans∗(n+m)∗N2∗M )
代码
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<queue>
#define Lint long long int
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=10010;
struct node
{
int next,to,c;
}t[MAXN*100];
struct task
{
int u,v,c;
}p[MAXN];
int head[MAXN],num;
int lev[MAXN];
int n,m,T,END;
queue<int> q;
void add(int u,int v,int c)
{
t[++num]=(node){ head[u],v,c };
head[u]=num;
}
bool bfs()
{
int tmp;
for(int i=0;i<=END;i++) lev[i]=0;
while( !q.empty() ) q.pop();
q.push( 0 ),lev[0]=1;
while( !q.empty() )
{
tmp=q.front(),q.pop();
for(int i=head[tmp],x; i!=-1 ;i=t[i].next)
{
x=t[i].to;
if( !lev[x] && t[i].c ) lev[x]=lev[tmp]+1,q.push( x );
}
}
return lev[END];
}
int dfs(int k,int fm)
{
if( k==END ) return fm;
int tmp=0,f;
for(int i=head[k],x; i!=-1 ;i=t[i].next)
{
x=t[i].to;
if( lev[x]==lev[k]+1 && t[i].c )
{
f=dfs( x,min( fm-tmp,t[i].c ) );
t[i].c-=f,t[i^1].c+=f,tmp+=f;
if( tmp==fm ) break ;
}
}
if( tmp<fm ) lev[k]=0;
return tmp;
}
int Dinic()
{
int F=0;
while( bfs() ) F+=dfs( 0,INF );
return F;
}
void modify()
{
for(int i=0;i<=num;i+=2) t[i].c+=t[i^1].c,t[i^1].c=0;
}
int main()
{
int u,v,c;
scanf("%d%d%d",&n,&m,&T);
END=(n+T+1)*n+1;
for(int i=0;i<=END;i++) head[i]=num=-1;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&c);
p[i]=(task){ u,v,c };
}
add( 0,1,T ),add( 1,0,0 );
for(int i=1;i<=n+T;i++)
{
modify();
for(int j=1;j<=m;j++) add( (i-1)*n+p[j].u,i*n+p[j].v,p[j].c ),add( i*n+p[j].v,(i-1)*n+p[j].u,0 );
for(int j=1;j<=n;j++) add( (i-1)*n+j,i*n+j,INF ),add( i*n+j,(i-1)*n+j,0 );
add( i*n+n,END,T ),add( END,i*n+n,0 );
if( Dinic()==T ) { printf("%d\n",i);break ; }
}
return 0;
}