uva 1161 Objective: Berlin (最大流)

uva 1161 Objective: Berlin

题目大意:你要从A地到B地去,并且最晚要在lt之前到达。现在给你m个航班信息,信息包括:起始地点,降落地点,载客上限,起飞时间,降落时间。中途转机要花费半小时的时间。问在lt之前,可以从A地到达B地的最多的游客数量。
解题思路:以航班为节点进行建图。设置超级源点,连向所有起点为A地的航班,容量为INF;设置超级汇点,使所有降落地点为B点且降落时间在lt之前的航班连向超级汇点。每个航班都要拆成两个节点,中间的边容量为该航班的载客上限。如果i航班的降落地点等于j航班的起始地点,且i航班的降落时间+30 <= j航班的起飞时间,则连接i + m结点(拆出来的结点)和j结点。建完图求最大流。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <map>
using namespace std;

const int N = 10006;
const int M = 1000005;
const int INF = 0x3f3f3f3f;
struct flight{
    int bp, ep, p, bt, et;
}G[N];
map<string, int> mp;
typedef long long ll;
int n, lt, m, id, s, t, ss, tt;
string S, T;
int ec, head[N], first[N], que[N], lev[N];
int Next[M], to[M], v[M];

void init() {
    mp.clear();
    ec = 0;
    id = 1;
    memset(first, -1, sizeof(first));
}

void addEdge(int a,int b,int c) {
    to[ec] = b;
    v[ec] = c;
    Next[ec] = first[a];
    first[a] = ec++;

    to[ec] = a;
    v[ec] = 0;
    Next[ec] = first[b];
    first[b] = ec++;
}

int BFS() {
    int kid, now, f = 0, r = 1, i;
    memset(lev, 0, sizeof(lev));
    que[0] = ss, lev[ss] = 1;
    while (f < r) {
        now = que[f++];
        for (i = first[now]; i != -1; i = Next[i]) {
            kid = to[i];    
            if (!lev[kid] && v[i]) {
                lev[kid] = lev[now] + 1;    
                if (kid == tt) return 1;
                que[r++] = kid;
            }
        }
    }
    return 0;
}

int DFS(int now, int sum) {
    int kid, flow, rt = 0;
    if (now == tt) return sum;
    for (int i = head[now]; i != -1 && rt < sum; i = Next[i]) {
        head[now] = i;  
        kid = to[i];
        if (lev[kid] == lev[now] + 1 && v[i]) {
            flow = DFS(kid, min(sum - rt, v[i]));
            if (flow) {
                v[i] -= flow;
                v[i^1] += flow;
                rt += flow;
            } else lev[kid] = -1;   
        }           
    }
    return rt;
}

int dinic() {
    int ans = 0;
    while (BFS()) {
        for (int i = 0; i <= tt; i++) {
            head[i] = first[i];
        }           
        ans += DFS(ss, INF);
    }
    return ans;
}   

int getTime(string str) {
    int a = (str[0] - '0') * 10 + (str[1] - '0');
    int b = (str[2] - '0') * 10 + (str[3] - '0');
    return a * 60 + b;
}

int input() {
    cin >> S >> T;          
    string lit;
    cin >> lit;
    lt = getTime(lit);
    scanf("%d", &m);
    string a, b;
    for (int i = 1; i <= m; i++) {
        cin >> a >> b;
        if (!mp.count(a)) mp[a] = id++;
        if (!mp.count(b)) mp[b] = id++;
        G[i].bp = mp[a], G[i].ep = mp[b];
        scanf("%d", &G[i].p);
        cin >> a >> b;
        G[i].bt = getTime(a);
        G[i].et = getTime(b);
    }
    if (!mp.count(S) || !mp.count(T)) return 0;
    s = mp[S], t = mp[T];
    ss = 0;
    tt = m * 2 + 1;
    return 1;
}

void build() {
    for (int i = 1; i <= m; i++) {
        flight f = G[i];
        if (f.bp == s) {
            addEdge(ss, i, INF);
        }
        if (f.ep == t && f.et <= lt) {
            addEdge(i + m, tt, INF);
        }
        addEdge(i, i + m, f.p);
        for (int j = 1; j <= m; j++) {
            if (i == j) continue;
            if (f.ep != G[j].bp) continue;
            if (f.et + 30 > G[j].bt) continue;
            addEdge(i + m, j, INF);
        }
    }   
}

int main() {
    while (scanf("%d\n", &n) != EOF) {
        init();
        int flag = input();
        if (!flag) {
            printf("0\n");  
            continue;
        } 
        build();
        printf("%d\n", dinic());
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值