bzoj1570 [JSOI2008]Blue Mary的旅行
Description
在一段时间之后,网络公司终于有了一定的知名度,也开始收到一些订单,其中最大的一宗来自B市。Blue Mary决定亲自去签下这份订单。为了节省旅行经费,他的某个金融顾问建议只购买U航空公司的机票。U航空公司的所有航班每天都只有一班,并且都是上午出发当天下午到达的,所以他们每人每天只能坐一班飞机。经过调查,他们得到了U航空公司经营的所有航班的详细信息,这包括每一航班的出发地,目的地以及最多能买到的某一天出发的票数。(注意: 对于一个确定的航班,无论是哪一天,他们最多能买到的那一天出发的票数都是相同的。) Blue Mary注意到他们一定可以只乘坐U航空公司的航班就从A市到达B市,但是,由于每一航班能买到的票的数量的限制,他们所有人可能不能在同一天到达B市。所以现在Blue Mary需要你的帮助,设计一个旅行方案使得最后到达B市的人的到达时间最早。
Input
第一行包含3个正整数N,M和T。题目中会出现的所有城市分别编号为1,2,…,N,其中城市A编号一定为1,城市B编号一定为N. U公司一共有M条(单向)航班。而连Blue Mary在内,公司一共有T个人要从A市前往B市。 以下M行,每行包含3个正整数X,Y,Z, 表示U公司的每一条航班的出发地,目的地以及Blue Mary最多能够买到的这一航班某一天出发的票数。(即:无论是哪一天,Blue Mary最多只能买到Z张U航空公司的从城市X出发到城市Y的机票。) 输入保证从一个城市到另一个城市的单向航班最多只有一个。
Output
仅有一行,包含一个正整数,表示最后到达B市的人的最早到达时间。假设他们第一次乘飞机的那一天是第一天。
Sample Input
3 3 5
1 2 1
2 3 5
3 1 4
1 2 1
2 3 5
3 1 4
Sample Output
6
HINT
约定:
2 <= N <= 50
1 <= M <= 2450
1 <= T <= 50
1 <= X,Y <= N
X != Y
1 <= Z <= 50
正解:最大流。
最大流+按时间拆点的裸套路。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define N (2000010) 6 #define inf (1<<30) 7 8 using namespace std; 9 10 struct edge{ int nt,to,flow,cap; }g[N]; 11 struct e{ int u,v,w; }e[2500]; 12 13 int id[52][310],head[N],q[N],d[N],S,T,n,m,t,num,cnt,ans,flow; 14 15 il int gi(){ 16 RG int x=0,q=1; RG char ch=getchar(); 17 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 18 if (ch=='-') q=-1,ch=getchar(); 19 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 20 return q*x; 21 } 22 23 il void insert(RG int from,RG int to,RG int cap){ 24 g[++num]=(edge){head[from],to,0,cap},head[from]=num; 25 g[++num]=(edge){head[to],from,0,0},head[to]=num; return; 26 } 27 28 il int bfs(RG int S,RG int T){ 29 for (RG int i=1;i<=cnt;++i) d[i]=0; 30 RG int h=0,t=1; q[t]=S,d[S]=1; 31 while (h<t){ 32 RG int x=q[++h],v; 33 for (RG int i=head[x];i;i=g[i].nt){ 34 v=g[i].to; 35 if (!d[v] && g[i].cap>g[i].flow){ 36 d[v]=d[x]+1,q[++t]=v; 37 if (v==T) return 1; 38 } 39 } 40 } 41 return d[T]; 42 } 43 44 il int dfs(RG int x,RG int T,RG int a){ 45 if (!a || x==T) return a; RG int v,f,flow=0; 46 for (RG int i=head[x];i;i=g[i].nt){ 47 v=g[i].to; 48 if (d[v]==d[x]+1 && g[i].cap>g[i].flow){ 49 f=dfs(v,T,min(a,g[i].cap-g[i].flow)); 50 if (!f){ d[v]=-1; continue; } 51 g[i].flow+=f,g[i^1].flow-=f; 52 flow+=f,a-=f; if (!a) return flow; 53 } 54 } 55 return flow; 56 } 57 58 il int maxflow(RG int S,RG int T){ 59 RG int flow=0; 60 while (bfs(S,T)) flow+=dfs(S,T,inf); 61 return flow; 62 } 63 64 int main(){ 65 #ifndef ONLINE_JUDGE 66 freopen("bluemary.in","r",stdin); 67 freopen("bluemary.out","w",stdout); 68 #endif 69 n=gi(),m=gi(),t=gi(),num=1,S=++cnt,T=++cnt; 70 for (RG int i=1;i<=m;++i) e[i].u=gi(),e[i].v=gi(),e[i].w=gi(); 71 for (RG int i=1;i<=n;++i) id[i][0]=++cnt; 72 insert(S,id[1][0],t),insert(id[n][0],T,inf); 73 while (++ans){ 74 for (RG int i=1;i<=n;++i) id[i][ans]=++cnt,insert(id[i][ans-1],id[i][ans],inf); 75 for (RG int i=1;i<=m;++i) insert(id[e[i].u][ans-1],id[e[i].v][ans],e[i].w); 76 insert(id[n][ans],T,inf),flow+=maxflow(S,T); if (flow==t) break; 77 } 78 cout<<ans; return 0; 79 }