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

本文探讨了二战时期英国皇家空军利用二分图最大匹配问题解决飞行员配对方案,以最大化派出飞机数量的问题。通过构建源汇模型,引入额外节点和边,实现最优解的求解。

 1736:飞行员配对方案问题

Time Limit:1000MS  Memory Limit:65536K
Total Submit:44 Accepted:29 Page View:286 Special Judged

[Submit]   [Status]   [Discuss]

Font Size:  Aa  Aa  Aa

Description

第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出

的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞

行员,另1 名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英

国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的

外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空

军一次能派出最多的飞机。

对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,

使皇家空军一次能派出最多的飞机。

Input

由文件input.txt提供输入数据。文件第1 行有2个正整数m和n。n是皇家空军的飞行

员总数(n<100);m是外籍飞行员数。外籍飞行员编号为1~m;英国飞行员编号为m+1~n。

接下来每行有2 个正整数i和j,表示外籍飞行员i可以和英国飞行员j配合。文件最后以2

个-1 结束。

Output

程序运行结束时,将最佳飞行员配对方案输出到文件output.txt 中。第1 行是最佳飞行
 
    
 
    
员配对方案一次能派出的最多的飞机数M。接下来M 行是最佳飞行员配对方案。每行有2

个正整数i和j,表示在最佳飞行员配对方案中,飞行员i和飞行员j 配对。

如果所求的最佳飞行员配对方案不存在,则输出‘No Solution!’。

Sample Input

5 10

1 7

1 8

2 6

2 9

2 10

3 7

3 8

4 7

4 8

5 10

-1 -1

Sample Output

4

1 7

2 9

3 8

5 10


「Solution」

一个二分图最大匹配问题。

考虑在二分图的基础上增加源S和汇T。

1、S向X集合中每个顶点连一条容量为1的有向边。

2、Y集合中每个顶点向T连一条容量为1的有向边。

3、XY集合之间的边都设为从A集合中的点到B集合之中的点,容量为1的有向边。

求网络最大流,流量就是匹配数,所有满流边是一组可行解。


「代码」
//Dinic By Joker0429
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 10020
#define INF 1 << 30
using namespace std;
int n, m, s, t, tot, ans, d[maxn], head[maxn], dist[maxn];
struct E
{
    int from, to, next, tab;
}edge[maxn];
   
void add_edge(int u, int v, int f)
{
    tot++;
    edge[tot].from = u, edge[tot].to = v, edge[tot].tab = f, edge[tot].next = head[u], head[u] = tot;
    tot++;
    edge[tot].from = v, edge[tot].to = u, edge[tot].tab = 0, edge[tot].next = head[v], head[v] = tot;
}
   
int dfs(int x, int low)
{
    int a;
    if (x == t) return low;
    for (int i = head[x]; i != -1; i = edge[i].next)
        if (edge[i].tab > 0 && dist[edge[i].to] == dist[x] + 1 && (a = dfs(edge[i].to, min(edge[i].tab, low))))
        {
            edge[i].tab -= a, edge[i^1].tab += a;
            return a;
        }
    return 0;
}
   
int bfs()
{
    int l, r, k;
    memset(dist,0xff,sizeof(dist));
    d[0] = 0;
    d[1] = s;
    l = 0, r = 1;
    dist[s] = 0;
    while (l < r)
    {
        k = d[++l];
        for (int i = head[k]; i != -1; i = edge[i].next)
            if (edge[i].tab > 0 && dist[edge[i].to] < 0) dist[edge[i].to] = dist[k] + 1, d[++r] = edge[i].to;
    }
    if (dist[t] > 0) return 1; else return 0;
}
   
void dinic()
{
    ans = 0;
    while (bfs()) ans += dfs(0,INF);
}
   
void print()
{
    if (ans == 0)
    {
        printf("No Sulotion\n");
        return;
    }
    printf("%d\n",ans);
    for (int i = 0; i <= tot; i += 2)
        if (edge[i].tab == 0 && edge[i].from != s && edge[i].to != t) printf("%d %d\n", edge[i].from, edge[i].to);
}
   
int main()
{
    int x, y;
    memset(head,0xff,sizeof(head));
    tot = -1;
    while (~scanf("%d %d", &m, &n))
    {
        s = 0, t = n + 1;
        for (int i = 1; i <= m; i++) add_edge(0, i, 1);
        for (int i = m+1; i <= n; i++) add_edge(i, t, 1);
        while (~scanf("%d %d", &x, &y)) if (x == -1 && y == -1) break; else add_edge(x, y, 1);
        dinic();
        print();
    }
    return 0;
}


转载于:https://www.cnblogs.com/joker0429/archive/2013/01/11/2909926.html

(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参 “话讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值