当前位置: 代码迷 >> 综合 >> 【bzoj1570】Blue Mary的旅行
  详细解决方案

【bzoj1570】Blue Mary的旅行

热度:72   发布时间:2023-12-05 12:42:32.0

题意

??给定一张有向图,每条边每天最多经过有限次,一个人每天只能经过一条边,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;
}
  相关解决方案