bzoj1570 [JSOI2008]Blue Mary的旅行

Posted wfj_2048

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

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 }

 

以上是关于bzoj1570 [JSOI2008]Blue Mary的旅行的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1570[JSOI2008]Blue Mary的旅行 动态加边网络流

bzoj 1570: [JSOI2008]Blue Mary的旅行

bzoj1570 [JSOI2008]Blue Mary的旅行

bzoj1570[JSOI2008]Blue Mary的旅行 动态加边网络流

BZOJ 1567: [JSOI2008]Blue Mary的战役地图

BZOJ 1567: [JSOI2008]Blue Mary的战役地图