线性规划与网络流24题 01飞行员分配方案问题

线性规划与网络流24题 01飞行员分配方案问题

题意:

飞行员分为国外国内两种。国外飞行员只能和指定国内飞行员配对,问最佳配对方式使得配对对数最大。

思路:

跑最大流。

源码:

EK

#include <cstdio>

#include <cstring>

#include <cmath>

#include <cstdlib>

#include <string>

#include <algorithm>

#include <iostream>

#include <queue>

#include <vector>

using namespace std;

#define inf (1000000000)

const int MAXN = 100 + 5;

int flow[MAXN][MAXN];

int org_flow[MAXN][MAXN];

int p[MAXN];

int n, m;

void init()

{

    memset(flow, 0, sizeof(flow));

    scanf("%d%d", &m, &n);

    for(int i = 1 ; i <= m ; i++)

        flow[0][i] = 1;

    for(int i = m + 1 ; i <= n ; i++)

        flow[i][n + 1] = 1;

    int u, v;

    for(;;){

        scanf("%d%d", &u, &v);

        if(u + v == -2)

            break;

        flow[u][v] = 1;

    }

    memcpy(org_flow, flow, sizeof(flow));

}

void check_flow()

{

    printf("flow\n");

    for(int i = 0 ; i <= n + 1 ; i++){

        for(int j = 0 ; j <= n + 1 ; j++)

            printf("%d ", flow[i][j]);

        printf("\n");

    }

    printf("flow\n");

}

queue<int>que;

int vis[MAXN], a[MAXN];

int EK()

{

    int ans = 0;

    while(1){

        while(!que.empty()) que.pop();

        memset(a, 0, sizeof(a));

        memset(vis, 0, sizeof(vis));

        memset(p, 0, sizeof(p));

        vis[0] = 1;

        a[0] = inf;

        p[0] = 0;

        que.push(0);

//        check_flow();

        while(!que.empty()){

            int org = que.front();  que.pop();

            for(int i = 0 ; i <= n + 1; i++){

                if(flow[org][i] && !vis[i]){

                    que.push(i);

                    a[i] = min(a[org], flow[org][i]);

                    vis[i] = 1;

                    p[i] = org;

                }

            }

 

        }

//        printf("p\n");

//        for(int i = 0 ; i <= n + 1 ; i++)

//            printf("%d ", p[i]);

//        printf("\np\n");

        if(a[n + 1] == 0)

            break;

        ans += a[n + 1];

        int s = n + 1;

        while(0 != s){

//            printf("s = %d\n", s);

            flow[p[s]][s] -= a[n + 1];

            flow[s][p[s]] += a[n + 1];

            s = p[s];

        }

    }

    return ans;

}

int main()

{

    freopen("air10.in", "r", stdin);

    init();

    printf("%d\n", EK());

    for(int i = 1 ; i <= m ; i++){

        for(int j = m + 1 ; j <= n ; j++)

            if(flow[i][j] != org_flow[i][j])

                printf("%d %d\n", i, j);

    }

    return 0;

}

Dinic

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <cmath>

#include <queue>

#include <vector>

#include <iostream>

#include <algorithm>

using namespace std;

#define inf (1000000000)

const int MAXN = 100 + 5;

int head[MAXN], cnt;

int m, n;

int d[MAXN], vis[MAXN];

queue<int>que;

struct Edge

{

    int u, v, flow, ne;

    int cap;

    Edge(){}

    Edge(int _u, int _v){u = _u, v = _v, ne = head[_u];}

}edge[MAXN * MAXN * 2];

void add_edge(int u, int v)

{

    edge[cnt] = Edge(u, v);

    edge[cnt].flow = 1, edge[cnt].cap = 1;

    head[u] = cnt++;

 

    edge[cnt] = Edge(v, u);

    edge[cnt].flow = 0, edge[cnt].cap = 0;

    head[v] = cnt++;

}

void init()

{

    scanf("%d%d", &m, &n);

    cnt = 0;

    memset(head, -1, sizeof(head));

    for(int i = 1 ; i <= m ; i++)

        add_edge(0, i);

    for(int i = m + 1 ; i <= n ; i++)

        add_edge(i, n + 1);

    int u, v;

    while(1){

        scanf("%d%d", &u, &v);

        if(u == -1)

            break;

        add_edge(u, v);

    }

}

bool BFS()

{

    memset(vis, 0, sizeof(vis));

    while(!que.empty()) que.pop();

    vis[0] = 1;

    d[0] = 0;

    que.push(0);

    while(!que.empty()){

        int u = que.front();  que.pop();

        for(int now = head[u] ; now != -1 ; now = edge[now].ne){

            int v = edge[now].v;

            if(!vis[v] && edge[now].flow > 0){

                vis[v] = 1;

                d[v] = d[u] + 1;

                que.push(v);

            }

        }

    }

    return vis[n + 1];

}

int DFS(int u, int a)

{

    if(u == n + 1 || a == 0)

        return a;

    int flow = 0, f;

    for(int now = head[u] ; now != -1 ; now = edge[now].ne){

        int v = edge[now].v;

        if(d[v] == d[u] + 1 && (f = DFS(v, min(edge[now].flow, a)))){

            edge[now].flow -= f;

            edge[now ^ 1].flow += f;

            flow += f;

            a -= f;

            if(a == 0)  break;

        }

    }

    return flow;

}

int Dinic()

{

    int ans = 0;

    while(BFS()){

        ans += DFS(0, inf);

    }

    return ans;

}

int main()

{

//    freopen("air0.in", "r", stdin);

    init();

    int ans = Dinic();

    if(ans){

        printf("%d\n", ans);

        for(int i = 0 ; i < cnt ; i++){

            int u = edge[i].u, v = edge[i].v;

            if(edge[i].flow != edge[i].cap && u!=0 && u!=n+1 && v!=0 && v!=n+1 && u <= m && v >= m + 1)

                printf("%d %d\n", u, v);

        }

    }

 

    else

        printf("No Solution!\n");

    return 0;

}

 

ISAP

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <cmath>

#include <iostream>

#include <algorithm>

#include <queue>

#include <vector>

using namespace std;

#define inf (1000000000)

const int MAXN = 100 + 5;

int m, n;

int head[MAXN], cnt;

int source, sink;

queue<int>que;

int p[MAXN];

int d[MAXN], cur[MAXN];

int vis[MAXN], num[MAXN];

struct Edge

{

    int u, v, flow, ne;

    int cap;

    Edge(){}

    Edge(int _u, int _v){u = _u, v = _v, ne = head[_u];}

}edge[MAXN * MAXN * 2];

void add_edge(int u, int v)

{

    edge[cnt] = Edge(u, v);

    edge[cnt].flow = 1, edge[cnt].cap = 1;

    head[u] = cnt++;

 

    edge[cnt] = Edge(v, u);

    edge[cnt].flow = 0, edge[cnt].cap = 0;

    head[v] = cnt++;

}

void init()

{

    cnt = 0;

    memset(head, -1, sizeof(head));

    scanf("%d%d", &m, &n);

    for(int i = 1 ; i <= m ; i++)

        add_edge(0, i);

    for(int i = m + 1 ; i <= n ; i++)

        add_edge(i, n + 1);

    int u, v;

    while(scanf("%d%d", &u, &v) && u != -1)

        add_edge(u, v);

    source = 0, sink = n + 1;

}

void BFS(int t)

{

    while(!que.empty()) que.pop();

    memset(vis, 0, sizeof(vis));

    memset(d, 0, sizeof(d));

    d[t] = 0;

    vis[t] = 1;

    que.push(t);

    while(!que.empty()){

        int u = que.front();    que.pop();

        for(int now = head[u] ; now != -1 ; now = edge[now].ne){

            int v = edge[now].v;

            if(vis[v] == 0){

                vis[v] = 1;

                d[v] = d[u] + 1;

                que.push(v);

            }

        }

    }

}

int Augment()

{

    int ans = inf;

    int now = sink;

    while(now != source){

        ans = min(ans, edge[p[now]].flow);

        now = edge[p[now]].u;

    }

    return ans;

}

int ISAP(int s, int t)

{

    BFS(t);

    int flow = 0;

    memset(num, 0, sizeof(num));

    for(int i = 0 ; i <= n + 1 ; i++)

        cur[i] = head[i];

    for(int i = 0 ; i <= n + 1 ; i++)

        num[d[i]]++;

    int u = s;

    while(d[s] < n + 1){

        if(u == t){

            flow += Augment();

            u = s;

        }

        int ok = 0;

        for(int &now = cur[u] ; now != -1 ; now = edge[now].ne){

            int v = edge[now].v;

            if(edge[now].flow > 0 && d[v] == d[u] - 1){

                ok = 1;

                p[v] = now;

                u = v;

                break;

            }

        }

        if(!ok){

            int tm = n + 1;

            for(int now = head[u] ; now != -1 ; now = edge[now].ne){

                if(edge[now].flow > 0)

                    tm = min(tm, d[edge[now].v]);

            }

            if(--num[d[u]] == 0)  break;

            num[tm + 1]++;

            d[u] = tm + 1;

            if(u != s) u = edge[p[u]].v;

        }

    }

    return flow;

}

int main()

{

    init();

    int ans = ISAP(source, sink);

    if(ans){

        printf("%d\n", ans);

        for(int i = 0 ; i < cnt ; i++){

            int u = edge[i].u, v = edge[i].v;

            if(edge[i].flow != edge[i].cap && u >= 1 && u <= m && v >= m + 1 && v <= n)

                printf("%d %d\n", u, v);

        }

    }

    return 0;

}

 

你可能感兴趣的:(线性规划与网络流24题 01飞行员分配方案问题)