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

来源:互联网 发布:excel筛选出多个数据 编辑:程序博客网 时间:2024/06/05 20:03

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.

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 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));
}
}
0 0
原创粉丝点击