UVALive - 3645 - Objective: Berlin(最大流 + 时序模型)

题意:给出n(n <= 150)个城市和m(m <= 5000)个航班,每个航班有出发地、到达地、乘坐人数、起飞时间和降落时间(时间用时和分表示),求一个指定城市到另一个指定城市在规定的最晚时间前可以过去多少人(换航班的间隔至少需要30分钟)。

1、为了考虑时间的因素,把航班拆成两个点v1与v2,则v1 -> v2的容量为航班的乘坐人数;

2、若两趟航班之间可以转(即第一个航班的降落时间与第二个航班的起飞时间至少相差30分钟),那么就将第一个航班的v2连到第二个航班的v1上去,容量为正无穷;

3、另设两个点分别代表出发与到达的指定城市 start 和 end,则:所有出发点为 start 的航班,连start -> 航班的v1,所有终点为 end 的航班,且到达时间在规定最晚时间之前的,连 航班的v2 -> end。容量均为正无穷;

4、对 start 至 end 求一遍最大流即可。

代码如下:

#include<cstdio>
#include<cstring>
#include<cctype>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<list>
#define fin freopen("in.txt", "r", stdin)
#define fout freopen("out.txt", "w", stdout)
#define pr(x) cout << #x << " : " << x << "   "
#define prln(x) cout << #x << " : " << x << endl
#define Min(a, b) a < b ? a : b
#define Max(a, b) a < b ? b : a
typedef long long ll;
typedef unsigned long long llu;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const double pi = acos(-1.0);
const double EPS = 1e-6;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const ll MOD = 1e9 + 7;
using namespace std;

#define NDEBUG
#include<cassert>
const int MAXN = 200 + 10;
const int MAXT = 10000 + 10;

struct Edge{
    int from, to, cap, flow;
    Edge(int a, int b, int c, int d) : from(a), to(b), cap(c), flow(d) {}
};

struct Dinic{
    int n, m, s, t;
    vector<Edge> edges;
    vector<int> G[MAXT];
    bool vis[MAXT];
    int d[MAXT];
    int cur[MAXT];
    void init(int k){
        edges.clear();
        for(int i = 0; i < k; ++i)  G[i].clear();
    }
    void AddEdge(int from, int to, int cap){
        edges.push_back(Edge(from, to, cap, 0));
        edges.push_back(Edge(to, from, 0, 0));
        m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }
    bool bfs(){
        memset(vis, false, sizeof vis);
        queue<int> q;
        q.push(s);
        d[s] = 0;
        vis[s] = true;
        while(!q.empty()){
            int x = q.front();  q.pop();
            for(int i = 0; i < G[x].size(); ++i){
                Edge &e = edges[G[x][i]];
                if(!vis[e.to] && e.cap > e.flow){
                    vis[e.to] = true;
                    d[e.to] = d[x] + 1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int dfs(int x, int a){
        if(x == t || a == 0)  return a;
        int flow = 0, f;
        for(int &i = cur[x]; i < G[x].size(); ++i){
            Edge &e = edges[G[x][i]];
            if(d[x] + 1 == d[e.to] && (f = dfs(e.to, Min(a, e.cap - e.flow))) > 0){
                e.flow += f;
                edges[G[x][i] ^ 1].flow -= f;
                flow += f;
                a -= f;
                if(a == 0)  break;
            }
        }
        return flow;
    }
    int Maxflow(int s, int t){
        this->s = s;  this->t = t;
        int flow = 0;
        while(bfs()){
            memset(cur, 0, sizeof cur);
            flow += dfs(s, INT_INF);
        }
        return flow;
    }
}dic;

map<string, int> mp;
int sumid, latest, n, m;
int getID(string t){
    if(mp.count(t))  return mp[t];
    return mp[t] = ++sumid;
}

int getTime(char s[]){
    return 60 * ((s[0] - '0') * 10 + s[1] - '0') + 10 * (s[2] - '0') + s[3] - '0';
}

struct Node{
    int u, v, t, t1, t2;
}p[MAXT];

int main(){
    while(scanf("%d", &n) == 1){
        mp.clear();
        sumid = 0;
        char s1[10], s2[10];
        scanf("%s%s", s1, s2);
        int s = getID(s1), t = getID(s2);
        scanf("%s%d", s1, &m);
        latest = getTime(s1);
        for(int i = 1; i <= m; ++i){
            scanf("%s%s", s1, s2);
            p[i].u = getID(s1);
            p[i].v = getID(s2);
            scanf("%d%s%s", &p[i].t, s1, s2);
            p[i].t1 = getTime(s1);
            p[i].t2 = getTime(s2);
        }
        dic.init(2 * m + 10);
        for(int i = 1; i <= m; ++i){
            dic.AddEdge(i, i + m, p[i].t);
            if(p[i].u == s)  dic.AddEdge(0, i, INT_INF);
            if(p[i].v == t && p[i].t2 <= latest)  dic.AddEdge(i + m, 2 * m + 1, INT_INF);
            for(int j = 1; j <= m; ++j){
                if(i == j)  continue;
                if(p[i].v == p[j].u && p[j].t1 - p[i].t2 >= 30)  dic.AddEdge(i + m, j, INT_INF);
            }
        }
        printf("%d\n", dic.Maxflow(0, 2 * m + 1));
    }
    return 0;
}

 

posted @ 2016-11-03 20:36  TianTengtt  阅读(165)  评论(0编辑  收藏  举报