LOJ6000搭配飞行员(网络流24题)

本文介绍了一种利用二分图匹配算法解决飞行任务中飞行员最优搭配问题的方法。通过构建二分图并运用最大流算法,实现飞行员与飞行任务间的最佳匹配,确保尽可能多的飞机能够成功起飞。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述
飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞机,这种飞机每架有两个驾驶员,需一个正驾驶员和一个副驾驶员。由于种种原因,例如相互配合的问题,有些驾驶员不能在同一架飞机上飞行,问如何搭配驾驶员才能使出航的飞机最多。

因为驾驶工作分工严格,两个正驾驶员或两个副驾驶员都不能同机飞行。

输入格式
第一行,两个整数 n n n 与 m m m,表示共有 n n n 个飞行员,其中有 m m m 名飞行员是正驾驶员。
下面有若干行,每行有 2 2 2 个数字 a a a、b b b。表示正驾驶员 a a a 和副驾驶员 b b b 可以同机飞行。
注:正驾驶员的编号在前,即正驾驶员的编号小于副驾驶员的编号。

输出格式
仅一行一个整数,表示最大起飞的飞机数。

样例
样例输入
10 5
1 7
2 6
2 10
3 7
4 8
5 9
样例输出
4
数据范围与提示
2≤n≤100


很水的一道题,最大流跑二分图匹配

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll ans; 
int n , m , S , T;
int linkk[110] , t;
int dep[110];
bool flag;
const ll oo = 1000000000000000000LL;
struct node{
    int n , y , v;
}e[100100];
int read()
{
    int sum = 0;char c = getchar();bool flag = true;
    while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
    while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
    if(flag)  return sum;
     else return -sum;
}  
void insert(int x,int y,int z)
{
    e[++t].y = y;e[t].n = linkk[x];e[t].v = z;linkk[x] = t;
    e[++t].y = x;e[t].n = linkk[y];e[t].v = 0;linkk[y] = t;
}
void init()
{
    t = 1;
    n = read();m = read();S = n + 1;T = n + 2;
    for(int i = 1;i <= m;++i) insert(S,i,1);
    for(int i = m + 1;i <= n;++i) insert(i,T,1);
    int a,b;
    while(scanf("%d",&a) != EOF)
    {
        b = read();
        insert(a,b,1);
    }
    return;
}
ll dfs(int x,ll lazy)
{
    if(x == T) return lazy;
    ll nowlazy = 0;
    ll d = 0;
    for(int i = linkk[x];i&&nowlazy < lazy;i = e[i].n)
    {
        int y = e[i].y;
        if(dep[y] == dep[x] + 1 && e[i].v > 0)
            if(d = dfs(y,min(1ll*e[i].v , lazy - nowlazy)))
            {
                nowlazy += d;
                e[i].v -= d;
                e[i^1].v += d; 
            }
    }
    if(nowlazy == 0) dep[x] = -1;
    return nowlazy;
}
queue<int>q;
bool bfs()
{
    memset(dep,-1,sizeof(dep));
    dep[S] = 0;q.push(S);
    while(q.size())
    {
        int v = q.front();
        for(int i = linkk[v];i;i = e[i].n)
            if(dep[e[i].y] == -1 && e[i].v > 0) 
                dep[e[i].y] = dep[v] + 1,q.push(e[i].y);
        q.pop();
    }
    if(dep[T] == -1) return false;
    return true;
}
int main()
{
    init();
    while(bfs())
    {       
        ll d;
        while(d = dfs(S,oo)) ans += d;
    }
    printf("%lld\n",ans);
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值