• 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 }
  • 相关阅读:
    C#生成安装文件后自动附加数据库的思路跟算法
    c#压缩和解压缩文件
    如何远程备份sql server数据库
    计算一年中的第几周/c#得到阳历对应农历日期
    C·处理数据库备份
    字符串提取替换后再替换回去 和 函数将数字转换中文数字
    Visual C#的Excel编程
    数据库备份和恢复
    blog
    请问谁知道DOTMSN中打开聊天对话框的方法是什么?
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7655402.html
Copyright © 2020-2023  润新知