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

【题目描述】

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

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

【输入格式】

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

【输出格式】

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

【输入样例】

10 5

1 7

2 6

2 10

3 7

4 8

5 9

【输出格式】

4

【备注】

2<=n<=100

【题目分析】

最裸的板子题,没有之一。

对于每个可以同机飞行的正副驾驶员,连一条容量为1的边,可以跑一次最大匹配或所有正驾驶员向s连容量为1的边,所有副驾驶向t连容量为1的边跑一遍最大流即可。

【代码~】

最大流【可做模板】

#include<bits/stdc++.h>
using namespace std;
const int MAXN=3010;
const int INF=0x3f3f3f3f;

int cnt,n,m,s,t;
int head[MAXN],depth[MAXN],cur[MAXN];
int nxt[MAXN],to[MAXN],w[MAXN];
queue<int> q;
int vis[MAXN];

bool bfs()
{
	while(!q.empty())
	  q.pop();
	memset(depth,0,sizeof(depth));
	depth[s]=1;
	q.push(s);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=head[u];i!=-1;i=nxt[i])
		{
			int v=to[i];
			if(depth[v]==0&&w[i]!=0)
			{
				depth[v]=depth[u]+1;
				q.push(v);
			}
		}
	}
	if(depth[t]==0)
	  return false;
	return true;
}

int dfs(int u,int dist)
{
	if(u==t)
	  return dist;
	for(int &i=cur[u];i!=-1;i=nxt[i])
	{
		int v=to[i];
		if(depth[v]==depth[u]+1&&w[i]>0)
		{
			int di=dfs(v,min(dist,w[i]));
			if(di>0)
			{
				w[i]-=di;
				w[i^1]+=di;
				return di;
			}
		}
	}
	return 0;
}

int dinic()
{
	int ans=0;
	while(bfs())
	{
		for(int i=s;i<=t;++i)
		  cur[i]=head[i];
		while(int d=dfs(s,INF))
		  ans+=d;
	}
	return ans;
}

void Add(int x,int y,int z)
{
	nxt[cnt]=head[x];
	head[x]=cnt;
	to[cnt]=y;
	w[cnt]=z;
	cnt++;
}

void add(int x,int y,int z)
{
	Add(x,y,z);
	Add(y,x,0);
}

int main()
{
	memset(head,-1,sizeof(head));
	memset(nxt,-1,sizeof(nxt));
	scanf("%d%d",&n,&m);
	s=0,t=n+1;
	for(int i=1;i<=m;++i)
	  add(s,i,1);
	for(int i=m+1;i<=n;++i)
	  add(i,t,1);
	int x,y;
	while(scanf("%d%d",&x,&y)!=EOF)
		add(x,y,1);
	printf("%d\n",dinic());
	return 0;
}

二分图最大匹配【匈牙利算法】

#include<bits/stdc++.h>
using namespace std;
const int MAXN=101;

int line[MAXN][MAXN];
int fp[MAXN],used[MAXN],m,n;

bool find(int x)
{
	for(int i=m+1;i<=n;++i)
	{
		if(line[x][i]&&!used[i])
		{
			used[i]=1;
			if(!fp[i]||find(fp[i]))
			{
				fp[i]=x;
				return true;
			}
		}
	}
	return false;
}

int main()
{
	int x,y;
	scanf("%d%d",&n,&m);
	memset(line,0,sizeof(line));
	memset(fp,0,sizeof(fp));
	while(scanf("%d%d",&x,&y)!=EOF)
	{
		line[x][y]=1;
	}
	int sum=0;
	for(int i=1;i<=m;++i)
	{
		memset(used,0,sizeof(used));
		if(find(i))
		  sum++;
	}
    cout<<sum;
	return 0;
}

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
问题编号 问题名称 问题模型 转化模型 1 飞行员配对方案问题 二分图最大匹配 网络最大流 2 太空飞行计划问题 最大权闭合图 网络最小割 3 最小路径覆盖问题 有向无环图最小路径覆盖 网络最大流 4 魔术球问题 有向无环图最小路径覆盖 网络最大流 5 圆桌问题 二分图多重匹配 网络最大流 6 最长递增子序列问题 最多不相交路径 网络最大流 7 试问题 二分图多重匹配 网络最大流 8 机器人路径规划问题 (未解决) 最小费用最大流 9 方格取数问题 二分图点权最大独立集 网络最小割 10 餐巾计划问题 线性规划网络优化 最小费用最大流 11 航空路线问题 最长不相交路径 最小费用最大流 12 软件补丁问题 最小转移代价 最短路径 13 星际转移问题 网络判定 网络最大流 14 孤岛营救问题 分层图最短路径 最短路径 15 汽车加油行驶问题 分层图最短路径 最短路径 16 数字梯形问题 最大权不相交路径 最小费用最大流 17 运输问题 网络费用量 最小费用最大流 18 分配问题 二分图最佳匹配 最小费用最大流 19 负载平衡问题 最小代价供求 最小费用最大流 20 深海机器人问题 线性规划网络优化 最小费用最大流 21 最长k可重区间集问题 最大权不相交路径 最小费用最大流 22 最长k可重线段集问题 最大权不相交路径 最小费用最大流 23 火星探险问题 线性规划网络优化 最小费用最大流 24 骑士共存问题 二分图最大独立集 网络最小割
网络是一种用于解决各种问题的算法,包括飞行员配对问题。在这个问题中,我们可以使用最大流算法来找到最优的配对方案。 首先,我们需要将问题转化为图论问题。我们可以将每个飞行员和机型看作图中的一个节点,并且在这些节点之间建立一些边,以反映它们之间的关系。具体来说,我们可以: - 对于每个飞行员,从源节点向该节点连一条容量为1的边; - 对于每个机型,从该节点向汇节点连一条容量为1的边; - 对于每个可行的飞行员-机型配对,从对应的飞行员节点向对应的机型节点连一条容量为1的边。 然后,我们可以使用最大流算法来找到从源节点到汇节点的最大流量。这个最大流量就是最优的配对方案的数量。最大流算法也可以找到实际的最优配对方案。 这里是一个使用 Python 实现最大流算法来解决飞行员配对问题的示例代码: ```python from typing import List, Tuple from collections import defaultdict import networkx as nx def find_best_pairings(pilots: List[str], planes: List[str], preferences: List[Tuple[str, str]]) -> Tuple[int, List[Tuple[str, str]]]: # Create a bipartite graph G = nx.DiGraph() G.add_node("source") G.add_node("sink") for p in pilots: G.add_edge("source", p, capacity=1) for t in planes: G.add_edge(t, "sink", capacity=1) for p, t in preferences: G.add_edge(p, t, capacity=1) # Compute the maximum flow max_flow_value, max_flow_dict = nx.maximum_flow(G, "source", "sink") # Extract the matching pairs from the flow dictionary pairs = [] for p in pilots: for t in planes: if max_flow_dict[p][t] == 1: pairs.append((p, t)) return max_flow_value, pairs ``` 这个函数接受三个参数:一个飞行员列表,一个机型列表和一个偏好列表。偏好列表是一个元组列表,每个元组表示一个飞行员和机型的偏好关系。 函数使用 NetworkX 库来创建和分析图,使用 `nx.DiGraph()` 创建一个有向图。然后,它添加源和汇节点,以及所有飞行员和机型节点。接下来,它为每个飞行员和机型之间的偏好创建一条容量为1的边。 然后,函数使用 `nx.maximum_flow()` 函数计算从源节点到汇节点的最大流量。最后,它从量字典中提取配对,并以元组列表的形式返回它们。 可以使用以下代码来测试 `find_best_pairings` 函数: ```python pilots = ["A", "B", "C", "D", "E"] planes = ["P1", "P2", "P3", "P4", "P5"] preferences = [("A", "P1"), ("B", "P2"), ("C", "P3"), ("D", "P4"), ("E", "P5")] max_flow_value, pairs = find_best_pairings(pilots, planes, preferences) print("Maximum flow:", max_flow_value) print("Pairs:", pairs) ``` 这将打印出最大流量和最优配对方案的列表。在这个例子中,我们的函数将打印出: ``` Maximum flow: 5 Pairs: [('A', 'P1'), ('B', 'P2'), ('C', 'P3'), ('D', 'P4'), ('E', 'P5')] ``` 这表示有5个配对是最优的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值