UVa1161 Objective: Berlin(最大流)

题目

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3602

Description

The administration of a well-known football team has made a study about the lack of support in
international away games. This study has concluded that the only reason for this lack of support is
the di?culty in organizing the travel arrangements. To help solving this problem, the administration
has asked you to build a program that computes the maximum number of people that can ?y from
a departure city to a destination city, using the available places in regular ?ights in a given day, and
arriving at or before a given time. When traveling from one city to another, a person may make multiple
transfers. Each transfer is, at least, 30 minutes long, i.e., the departure time should be, at least 30
minutes after the arrival time. Given a set of ?ights for a single day and the latest arrival time, your
program should compute the maximum number of persons that can ?y, directly or indirectly, from a
departure city to a destination city, arriving at or before the latest arrival time.

Input

The input will contain several test cases, each of them as described below. Consecutive
test cases are separated by a single blank line.
The ?rst line contains an integer (smaller or equal to 150) indicating the number of cities that have
?ight connections. The second line contains a string indicating the city of departure. The third line
contains a string indicating the destination city. The fourth line contains the latest arrival time, in the
format HHMM, where HH is the hour in the day (from 00 to 23) and MM is the minute in the hour
(from 00 to 59). The ?fth line contains an integer N (smaller or equal to 5000), with the number of
existing ?ights. Each of the following N lines contains the info for each ?ight. Each such line contains
two strings and three integers, separated by blank spaces, O E C D A, where O and E are, respectively,
the origin and destination of a ?ight, C is the number of available places in the ?ight (from 0 to 300),
and D and A are the departure and arrival times in the previously de?ned format HHMM. All ?ights
start and end in the same day. City names may have up to 8 characters.
Output
For each test case, the output must follow the description below.
The output consists of one single line with an integer stating the maximum number of people that
can ?y from the origin to the destination city, using the given ?ights and arriving at or before the given
latest arrival time.

Sample Input

4
lisbon
berlin
1500
9
lisbon london 6 1000 1100
london lisbon 6 1130 1230
lisbon paris 5 1000 1100
paris lisbon 4 1130 1230
london paris 1 1130 1300
london berlin 2 1340 1510
berlin london 2 1300 1430
paris berlin 10 1330 1500
berlin paris 9 1300 1430

Sample Output

6

分析

题目大概说有n个城市和m条航线,每条航线都是从某一时刻某一城市出发在某一时刻到达某一城市,且各条航线都有最多人数的限制。现在已知出发城市和目的地城市以及一个最终的时刻,问最多有多少人能在最终时刻前到达目的地。

这题自然会去想把城市看成点,航线看成边。这样的话城市需要按照时间拆点24*60*100=144000,太多了。。然而事实上有连边的点最多只会有2*m个,即10000个,其他10多W都是摆设,所以其实也OK吧。

这题的正解是:

  • 把航线看成点,并且拆成两点x和x‘,x表示航线开始,另一点x‘表示航线结束;
  • 新建源点汇点,源点向所有从出发城市是起始城市的航线x连容量INF的边,所有到达城市是目的地且到达时间在最终时刻之前的航线x‘向汇点连容量INF的边;
  • 所有航线,x向x‘连容量为航线限制人数的边,这样就表示航线从开始到结束最多能流过的人数;
  • 对于所有的A航线和B航线,满足A航线到达城市为B航线出发城市 且 A航线到达时刻+30分钟在B航线开始时刻之前,由A‘到B连容量INF的边,这样就表示A航线结束后可以起身开始进行B航线;
  • 跑最大流就是结果了。

其实,这个解法也能看成是把城市按时间拆点并离散化。

不过没想到真的是10000个点去跑网络流。。另外,思维不要局限,图中的点和边可以是各种东西。。要大胆建图跑网络流。。

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 11111
#define MAXM 2222222

struct Edge{
    int v,cap,flow,next;
}edge[MAXM];
int vs,vt,NE,NV;
int head[MAXN];

void addEdge(int u,int v,int cap){
    edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0;
    edge[NE].next=head[u]; head[u]=NE++;
    edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0;
    edge[NE].next=head[v]; head[v]=NE++;
}

int level[MAXN];
int gap[MAXN];
void bfs(){
    memset(level,-1,sizeof(level));
    memset(gap,0,sizeof(gap));
    level[vt]=0;
    gap[level[vt]]++;
    queue<int> que;
    que.push(vt);
    while(!que.empty()){
        int u=que.front(); que.pop();
        for(int i=head[u]; i!=-1; i=edge[i].next){
            int v=edge[i].v;
            if(level[v]!=-1) continue;
            level[v]=level[u]+1;
            gap[level[v]]++;
            que.push(v);
        }
    }
}

int pre[MAXN];
int cur[MAXN];
int ISAP(){
    bfs();
    memset(pre,-1,sizeof(pre));
    memcpy(cur,head,sizeof(head));
    int u=pre[vs]=vs,flow=0,aug=INF;
    gap[0]=NV;
    while(level[vs]<NV){
        bool flag=false;
        for(int &i=cur[u]; i!=-1; i=edge[i].next){
            int v=edge[i].v;
            if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){
                flag=true;
                pre[v]=u;
                u=v;
                //aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
                aug=min(aug,edge[i].cap-edge[i].flow);
                if(v==vt){
                    flow+=aug;
                    for(u=pre[v]; v!=vs; v=u,u=pre[u]){
                        edge[cur[u]].flow+=aug;
                        edge[cur[u]^1].flow-=aug;
                    }
                    //aug=-1;
                    aug=INF;
                }
                break;
            }
        }
        if(flag) continue;
        int minlevel=NV;
        for(int i=head[u]; i!=-1; i=edge[i].next){
            int v=edge[i].v;
            if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
                minlevel=level[v];
                cur[u]=i;
            }
        }
        if(--gap[level[u]]==0) break;
        level[u]=minlevel+1;
        gap[level[u]]++;
        u=pre[u];
    }
    return flow;
}

int covert_time(int t){
    return t/100*60+t%100;
}

string city[111];

string from[5555],to[5555];
int cap[5555],s[5555],t[5555];

int main(){
    int n,m;
    while(cin>>n){
        string s_city,t_city;
        cin>>s_city>>t_city;

        int deadline; cin>>deadline;
        deadline=covert_time(deadline);

        cin>>m;
        for(int i=1; i<=m; ++i){
            cin>>from[i]>>to[i]>>cap[i]>>s[i]>>t[i];
            s[i]=covert_time(s[i]);
            t[i]=covert_time(t[i]);
        }

        vs=0; vt=m*2+1; NV=vt+1; NE=0;
        memset(head,-1,sizeof(head));
        for(int i=1; i<=m; ++i){
            if(from[i]==s_city) addEdge(vs,i,INF);
            if(to[i]==t_city && t[i]<=deadline) addEdge(i+m,vt,INF);
            addEdge(i,i+m,cap[i]);
        }
        for(int i=1; i<=m; ++i){
            for(int j=1; j<=m; ++j){
                if(i==j) continue;
                if(to[i]==from[j] && t[i]+30<=s[j]) addEdge(i+m,j,INF);
            }
        }
        printf("%d\n",ISAP());
    }
    return 0;
}
时间: 2024-11-06 22:27:05

UVa1161 Objective: Berlin(最大流)的相关文章

UVa 1161 Objective: Berlin (最大流)

题意:给定一些航班,每个航班有人数,和起始终止时间,每次转机要花半小时,问限制时间内最多能有多少人从起始城市到终点城市. 析:差不多是裸板网络流的最大流问题,把每个航班都拆成两个点,这两个点之间连接一条流量为这个航班的容量,然后再暴力去查看能不能连接,如果能, 那么就连接一条容量无限的边,然后在源点和汇点加一个无限的容量边. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #

uva 1161 Objective: Berlin (最大流)

uva 1161 Objective: Berlin 题目大意:你要从A地到B地去,并且最晚要在lt之前到达.现在给你m个航班信息,信息包括:起始地点,降落地点,载客上限,起飞时间,降落时间.中途转机要花费半小时的时间.问在lt之前,可以从A地到达B地的最多的游客数量. 解题思路:以航班为节点进行建图.设置超级源点,连向所有起点为A地的航班,容量为INF:设置超级汇点,使所有降落地点为B点且降落时间在lt之前的航班连向超级汇点.每个航班都要拆成两个节点,中间的边容量为该航班的载客上限.如果i航班

UVA 1161 - Objective: Berlin(网络流)

UVA 1161 - Objective: Berlin 题目链接 题意:给定一些航班,每个航班有人数,和起始终止时间,每次转机要花半小时,问限制时间内最多能有多少人从起始城市到终点城市 思路:以航班为结点建图,航班有容量限制所以进行拆点,然后两个航班如果终点和起点对上,并且时间满足就可以建边,然后源点连向起点为起始的航班,终点为终点的航班连向汇点(要在时间不超过时限的情况下),建好图跑一下最大流就可以了 代码: #include <cstdio> #include <cstring&g

UVALIVE 3645 Objective: Berlin

最大流 .以航班为节点进行最大流. 容量限制进行拆点. 如果时间地点满足可以建一条边. 具体看代码.变量名被修改过了.一开始的变量名可能比较容易看懂 但CE了.可能与库里的变量重复了. AC代码 #include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #

Objective-C的IO流

HDU4309-Seikimatsu Occult Tonneru(最大流)

Seikimatsu Occult Tonneru Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1741    Accepted Submission(s): 438 Problem Description During the world war, to avoid the upcoming Carpet-bombing fro

HDU 4183 Pahom on Water(最大流SAP)

Pahom on Water Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 629    Accepted Submission(s): 288 Problem Description Pahom on Water is an interactive computer game inspired by a short story of

hdu 4183 EK最大流算法

欢迎参加——每周六晚的BestCoder(有米!) Pahom on Water Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 678    Accepted Submission(s): 312 Problem Description Pahom on Water is an interactive computer game ins

delphi 10.1 Berlin 中使用自带的 Base64 编码

delphi 10.1 berlin版本中,有好几个 base64 编码的单元可以使用,例如 Indy, MessageDigest_5,还有 CnBase64,我现在使用自带的 System.NetEncoding. var params: string; Digest: TBytes; Base64: TBase64Encoding; begin Base64 := TBase64Encoding.Create; params := Base64.EncodeBytesToString(Di