【bzoj1570】Blue Mary的旅行

来源:互联网 发布:运营美工对骂动态图 编辑:程序博客网 时间:2024/05/27 16:41

题意

  给定一张有向图,每条边每天最多经过有限次,一个人每天只能经过一条边,T个人从1号点出发,问多少天之后能到达n

解法

分层图+最大流:
  一开始没有看见每一个人每天只能走一条边这个条件,所以就WA了很多次
  对每一天建一层图,并且上下两层之间要联通,然后每一层的n号点也要和汇点联通,那么我们可以对这个分层图求最大流,如果最大流T,显然经过的层数就是答案
  为了方便,我们可以枚举天数,逐天进行加边,每加完一天的边就跑一次最大流,如果如何条件,即是答案,否则复原原图,继续下一天

复杂度

O(ansn+mN2M

代码

#include<iostream>#include<cstdlib>#include<cstdio>#include<queue>#define Lint long long intusing 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;}