您的位置:首页 > 理论基础 > 计算机网络

(beginer) 网络流(拆点+时序模型) UVA 1161 - Objective: Berlin

2014-02-08 09:55 363 查看
Objective:
Berlin

 

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 difficulty 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 fly from a departure city to a
destination city, using the available places in regular flights 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 flights for a single day and the latest arrival time, your
program should compute the maximum number of persons that can fly, directly or
indirectly, from a departure city to a destination city, arriving at or before
the latest arrival time.

InputThe input will contain several
test cases, each of them as described below. Consecutive test cases are
separated by a single blank line.


The first line
contains an integer (smaller or equal to 150) indicating the number of cities
that have flight 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 fifth line contains an integer N (smaller or equal to
5000), with the number of existing flights.

Each of the
following N lines contains the info for each flight. 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 flight, C is the number of
available places in the flight (from 0 to 300), and D and A are the departure
and arrival times in the previously defined format HHMM. All flights start and
end in the same day. City names may have up to 8
characters.

Output
For each test case,
the output consists of one single line with an integer stating the maximum
number of people that can fly from the origin to the destination city, using the
given flights 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

题意:给出了很多个航班和他们的起飞和降落的时间地点以及他们的最大载客量,也给出了起点和终点,问在规定时间内,最多能有多少人能从起点飞到终点。其中转乘需要另外耗费30分钟,即如果从一架飞机下来后,要等多30分钟才能继续坐飞机。
思路:这个题目建图不能直接按题目给的建,要把一个航班看成一个点,然后如果航班之间能互相换乘,就加有向边,最后我们能得到一个有向图,其中点有对应的容量,这时候我们能想到用网络流来做,我们把节点拆成2个点,拆开的点连在一起,容量是飞机的容量,其他边的容量为无穷大,另外我们还要加一个源点,连向所有起飞地点是起点的航班,然后加一个汇点,所有降落地点是终点的航班都指向这个汇点。最后套用网络流模板。注意我们这样建图会会有很多个节点的,数组别开小了。而且不一定是连通的,套模板的时候注意看会不会越界啊。
代码:#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<map>#include<string.h>#include<string>using namespace std;const int maxn = 15000+5;const int inf = 1e8;int n , m , limit , size;char buffer[100];vector<int> S , T;string src , dest;inline int getminute(int x) { return x/100*60+x%100;}
struct Flight{ Flight(string ss, string tt,int lea,int arr,int ca) : s(ss) , t(tt) , leave(lea) , arrive(arr) , cap(ca) { } string s , t; int cap; int leave , arrive;};
vector<Flight> flight;
struct Edge{ Edge(int uu,int vv,int fl,int ca) : u(uu) , v(vv) , flow(fl) , cap(ca) { } int u , v; int flow , cap;};
vector<Edge> edge;vector<int> G[maxn];
void add(int s,int t,int cap){ edge.push_back(Edge(s,t,0,cap)); edge.push_back(Edge(t,s,0,0)); int x = edge.size(); G[s].push_back(x-2); G[t].push_back(x-1);}
void input(){ scanf("%s",buffer); src = buffer; scanf("%s",buffer); dest = buffer; scanf("%d%d",&limit,&m); limit = getminute(limit); flight.clear(); while (m--) { string u , v; int leave , arr , cap; scanf("%s",buffer); u = buffer; scanf("%s",buffer); v = buffer; scanf("%d%d%d",&cap,&leave,&arr); leave = getminute(leave); arr = getminute(arr); if (leave > limit || arr > limit) continue; flight.push_back(Flight(u,v,leave,arr,cap)); }}
void BuildGraph(){ for (int i = 0 ; i < maxn ; ++i) G[i].clear(); edge.clear(); S.clear() , T.clear(); size = flight.size(); for (int i = 0 ; i < flight.size() ; ++i) { if (flight[i].leave > limit || flight[i].arrive > limit) continue; if (flight[i].s==src) S.push_back(i); if (flight[i].t==dest) T.push_back(i+size); add(i,i+size,flight[i].cap); for (int j = 0 ; j < flight.size() ; ++j) if (i!=j)  { if (flight[j].leave > limit || flight[j].arrive > limit) continue; if (flight[i].t!=flight[j].s) continue; if (flight[i].arrive+30>flight[j].leave) continue; add(i+size,j,inf); } } for (int i = 0 ; i < S.size() ; ++i)  add(size+size,S[i],inf); for (int i = 0 ; i < T.size() ; ++i) add(T[i],size+size+1,inf); n = size*2+2;}
struct ISAP{ int s , t; int d[maxn] , num[maxn] , p[maxn] , cur[maxn]; void bfs()  { queue<int> q; q.push(t); for (int i = 0 ; i < n ; ++i) d[i] = inf; d[t] = 0; while (q.size())  { int u = q.front(); q.pop(); for (int i = 0 ; i < G[u].size() ; ++i) { Edge & e = edge[G[u][i]]; if (e.cap==0 && d[e.v]==inf) { d[e.v] = d[u]+1; q.push(e.v); } } } }
int Augment() { int x = t , a = inf; while (x!=s) { Edge & e = edge[p[x]]; a = min(a,e.cap-e.flow); x = e.u; } x = t; while (x!=s) { edge[p[x]].flow += a; edge[p[x]^1].flow -= a; x = edge[p[x]].u; } return a; }
int maxflow(int s,int t) { this->s = s , this->t = t; memset(num,0,sizeof(num)); memset(cur,0,sizeof(cur)); bfs(); for (int i = 0 ; i < n ; ++i)  { if (d[i]==inf) continue; ++num[d[i]]; } int x = s , flow = 0;; while (d[s] < n) { if (x==t) { flow += Augment(); x = s; } bool ok = false; for (int i = cur[x] ; i < G[x].size() ; ++i) { Edge & e = edge[G[x][i]]; if (e.cap > e.flow && d[x]==d[e.v]+1) { p[e.v] = G[x][i]; cur[x] = i; ok = true; x = e.v; break; } } if (!ok) { int k = n-1; for (int i = 0 ; i < G[x].size() ; ++i) { Edge & e = edge[G[x][i]]; if (e.cap > e.flow) k = min(k,d[e.v]); } --num[d[x]]; if (num[d[x]]==0) break; cur[x] = 0; ++num[d[x]=k+1]; if (x!=s) x = edge[p[x]].u; } } return flow; }
}solver;
int main(){ while (scanf("%d",&n)==1) { input(); BuildGraph(); printf("%d\n",solver.maxflow(n-2,n-1)); }}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: