「网络流24题」飞行员配对方案问题

传送门:>Here<

题意:二分图匹配输出方案

思路分析

学会了最大流再也不用敲匈牙利了哈哈……

最大流可以直接解决二分图匹配问题,方法是:将左侧节点与右侧节点的无向边全都变为容量为1的弧(正反),源点一一连向左侧节点,右侧节点一一连向汇点。跑最大流即可

关于为什么这样做是正确的,可以参见算法导论中有严格的证明。但其实这是一目了然的,由于所有弧的容量都为1,从源点连向左侧节点也就意味着最多只有1的流量到达每个节点。这个1就代表了这个节点只能被匹配一次。而右侧节点到汇点的容量也是1,意味着右侧节点也只能被匹配一次。在这样的约束条件下的最大流就是最大匹配了

关于输出方案则更简单,由于前面提到了容量都是1,所以一个点出发肯定只有一条有流量的弧,且流量=容量=1。所以求解最大匹配的方案实际上就是在左右两侧节点之间的弧内取出所有的有流量的弧。所有有流量的弧即为答案

Code

注意因为要统计答案,邻接表在存储的时候还要多加一个from记录起点

/*By DennyQi*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define  r  read()
#define  Max(a,b)  (((a)>(b)) ? (a) : (b))
#define  Min(a,b)  (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int MAXN = 1010;
const int MAXM = 10010;
const int INF = 1061109567;
inline int read(){
    int x = 0; int w = 1; register int c = getchar();
    while(c ^ ‘-‘ && (c < ‘0‘ || c > ‘9‘)) c = getchar();
    if(c == ‘-‘) w = -1, c = getchar();
    while(c >= ‘0‘ && c <= ‘9‘) x = (x << 3) +(x << 1) + c - ‘0‘, c = getchar(); return x * w;
}
int M,N,S,T,x,y,_begin;
int first[MAXM*2],nxt[MAXM*2],from[MAXM*2],to[MAXM*2],cap[MAXM*2],flow[MAXM*2],num_edge=-1;
int level[MAXN],cur[MAXN];
queue <int> q;
inline void add(int u, int v, int c, int f){
    to[++num_edge] = v;
    cap[num_edge] = c;
    flow[num_edge] = f;
    from[num_edge] = u;
    nxt[num_edge] = first[u];
    first[u] = num_edge;
}
inline bool BFS(){
    memset(level, 0, sizeof(level));
    while(!q.empty()) q.pop();
    q.push(S);
    level[S] = 1;
    int u,v;
    while(!q.empty()){
        u = q.front(); q.pop();
        for(int i = first[u]; i != -1; i = nxt[i]){
            v = to[i];
            if(!level[v] && cap[i]-flow[i] > 0){
                level[v] = level[u] + 1;
                q.push(v);
            }
        }
    }
    return level[T]!=0;
}
int DFS(int u, int a){
    if(u == T || a == 0) return a;
    int ans=0,v,_f;
    for(int& i = cur[u]; i != -1; i = nxt[i]){
        v = to[i];
        if(level[u]+1==level[v] && cap[i]>flow[i]){
            _f = DFS(v, Min(a, cap[i]-flow[i]));
            ans += _f, a -= _f;
            flow[i] += _f, flow[i^1] -= _f;
            if(a == 0) break;
        }
    }
    return ans;
}
inline void Dinic(){
    int tot = 0;
    while(BFS()){
        for(int i = S; i <= T; ++i) cur[i] = first[i];
        tot += DFS(S, INF);
    }
    printf("%d\n", tot);
}
int main(){
    freopen(".in","r",stdin);
    M=r,N=r;
    memset(first, -1, sizeof(first));
    S=0, T=N+1;
    for(int i = 1; i <= M; ++i){
        add(S, i, 1, 0);
        add(i, S, 0, 0);
    }
    for(int i = M+1; i <= N; ++i){
        add(i, T, 1, 0);
        add(T, i, 0, 0);
    }
    _begin = num_edge + 1;
    for(;;){
        x=r, y=r;
        if(x==-1 && y==-1) break;
        add(x, y, 1, 0);
        add(y, x, 0, 0);
    }
    Dinic();
    for(int i = _begin; i <= num_edge; ++i){
        if(cap[i]-flow[i] == 0 && cap[i]==1){
            printf("%d %d\n", from[i], to[i]);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/qixingzhi/p/9418204.html

时间: 2024-10-07 08:49:56

「网络流24题」飞行员配对方案问题的相关文章

【网络流24题】飞行员配对方案问题

[网络流24题]飞行员配对方案问题 题面 这些题都用Cogs交算了 因为cogs有SPJ 题面 题解 很简单的二分图匹配 匈牙利算法就能够解决 求最大流的话 再加上一个源点一个汇点即可 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set>

dinic求解二分图最大匹配&amp;&amp;网络流24题之飞行员配对方案问题

在二分图的基础上增加源S和汇T.1.S向X集合中每个顶点连一条容量为1的有向边.2.Y集合中每个顶点向T连一条容量为1的有向边.3.XY集合之间的边都设为从A集合中的点到B集合之中的点,容量为1的有向边. 求网络最大流,流量就是匹配数,所有满流边是一组可行解. 所以就解决了. 飞行员配对方案问题: 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外

「网络流24题」1. 飞行员配对方案问题

「网络流24题」1. 飞行员配对方案问题 <题目链接> 比较经典的一道二分图最大匹配. 匈牙利算法走起啊. 算出答案后,输出每个外籍飞行员匹配的点(如果有)即可. 匈牙利算法,简而言之就是,每个x部点u去找自己能匹配上的第一个y部点v,如果v还没有被匹配,或是v已经匹配的x部点w还能匹配其他y部点)就将x与y匹配. 「如果我除了她(v)还能追到别的妹子,我就把她让给你.」--w对x如是说. 代码简明易懂. #include <cstdio> #include <cstring

LiberOJ #6000. 「网络流 24 题」搭配飞行员 最大匹配

#6000. 「网络流 24 题」搭配飞行员 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞机,这种飞机每架有两个驾驶员,需一个正驾驶员和一个副驾驶员.由于种种原因,例如相互配合的问题,有些驾驶员不能在同一架飞机上飞行,问如何搭配驾驶员才能使出航的飞机最多. 因为驾驶工作分工严格,两个正驾驶员或两个副驾驶员都不能同机飞行. 输入格式 第一

「网络流24题」 题目列表

「网络流24题」 题目列表 序号 题目标题 模型 题解 1 飞行员配对方案问题 二分图最大匹配 <1> 2 太空飞行计划问题 最大权闭合子图 <2> 3 最小路径覆盖问题 二分图最小路径覆盖 <3> 4 魔术球问题 <4> 5 圆桌问题 <5> 6 最长递增子序列问题 <6> 7 试题库问题 <7> 8 机器人路径规划问题 <8> 9 方格取数问题 二分图最大点权独立集 <9> 10 餐巾计划问题

LiberOJ 6004. 「网络流 24 题」圆桌聚餐 网络流版子题

#6004. 「网络流 24 题」圆桌聚餐 内存限制:256 MiB时间限制:5000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 假设有来自 n nn 个不同单位的代表参加一次国际会议.每个单位的代表数分别为 ri r_ir?i??.会议餐厅共有 m mm 张餐桌,每张餐桌可容纳 ci c_ic?i?? 个代表就餐.为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐. 试设计一个算法,给出满足要求的

LibreOJ #6001. 「网络流 24 题」太空飞行计划 最大权闭合图

#6001. 「网络流 24 题」太空飞行计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合 E={E1,E2,?,Em} E = \{ E_1, E_2, \cdots, E_m \}E={E?1??,E?2??,?,E?m??},和进行这些实验

LiberOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题

#6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 G 公司有 n nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n nn 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入格式 文件的第 1 11 行中有 1 11 个正整数 n nn,表示有 n nn 个仓库.第 2 22 行中有 n nn 个

LiberOJ #6002. 「网络流 24 题」最小路径覆盖

#6002. 「网络流 24 题」最小路径覆盖 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 给定有向图 G=(V,E) G = (V, E)G=(V,E).设 P PP 是 G GG 的一个简单路(顶点不相交)的集合.如果 V VV 中每个顶点恰好在 P PP 的一条路上,则称 P PP 是 G GG 的一个路径覆盖.P PP 中路径可以从 V VV 的任何一个顶点开始,