Objective: Berlin UVALive - 3645
网络流·最大流
题目大意:
有n个城市,m条航班。已知每条航班的起点和终点,还有每条航班的载客量、出发时间、到达时间。并且要求在任何一个城市(起点、终点除外)都至少要有30分钟的中转时间,求起点到终点的最大客流量。
题解:
将航线视作一个点,如果航线u能经过某城市中转到航线v,则从u连一条弧到v。构造好图之后拆点,将点u拆成u和u’,对于任意一个u,都连一条弧从u到u’,容量为航线上的载客量;对于节点u,从u’向u邻接的节点v连一条弧,容量为无穷大;增加源点s,从s向起点为出发点的航线u连一条弧,容量为无穷大,增加汇点t,从终点为目标点的航线v对应的v’向t连一条弧,容量也为无穷大。最后,答案就是最大流。
Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
const int N = 20005;
const int M = 1e6+5;
const int INF = 0x3f3f3f3f;
int n,m,S,T;
string ss,tt;
int timelimit;
struct Node{
string u,v; int c,st,et;
} fly[N];
struct edge{
int to,cap,flow,next;
} e[M*2];
int head[N],ec=1;
void clear(){ memset(head,0,sizeof(head)); ec=1; }
void add(int a,int b,int cap){
ec++; e[ec].to=b; e[ec].cap=cap; e[ec].flow=0;
e[ec].next=head[a]; head[a]=ec;
}
void add2(int a,int b,int cap){
// D(a); D(b); D(cap); E;
add(a,b,cap); add(b,a,0);
}
bool vis[N]; int d[N];
bool bfs(){
memset(vis,false,sizeof(vis));
queue<int> q; q.push(S); vis[S]=true; d[S]=0;
while(!q.empty()){
int u=q.front(); q.pop();
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(!vis[v] && e[i].cap>e[i].flow){
d[v]=d[u]+1; vis[v]=true;
q.push(v);
if(v==T) return true;
}
}
}
return false;
}
int dfs(int u,int a){
if(u==T || a==0) return a;
int flow=0, f;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(d[v]==d[u]+1 && (f=dfs(v,min(a,e[i].cap-e[i].flow)))){
flow+=f; a-=f;
e[i].flow+=f; e[i^1].flow-=f;
if(a==0) break;
}
}
if(a) d[u]=-1;
return flow;
}
int mxf(){
int flow=0;
while(bfs()){
flow+=dfs(S,INF);
}
return flow;
}
int func(int a,int b){
int t1=(a/100)*60+a%100;
int t2=(b/100)*60+b%100;
return t1-t2;
}
int main(){
freopen("a.in","r",stdin);
while(cin>>n){
clear();
cin>>ss>>tt>>timelimit;
cin>>m; S=0; T=m*2+1;
// D(S); D(T); E;
for(int i=1;i<=m;i++){
cin>>fly[i].u>>fly[i].v>>fly[i].c>>fly[i].st>>fly[i].et;
}
for(int i=1;i<=m;i++){
if(fly[i].u==ss) add2(S,i*2-1,INF);
if(fly[i].v==tt && fly[i].et<=timelimit) add2(i*2,T,INF);
add2(i*2-1,i*2,fly[i].c);
for(int j=1;j<=m;j++){
if(i==j) continue;
if(fly[i].v==fly[j].u && func(fly[j].st,fly[i].et)>=30)
add2(i*2,j*2-1,INF);
}
}
int ans=mxf();
printf("%d\n",ans);
}
}