【洛谷 P2756】飞行员配对方案问题【二分图の最大匹配】

题目背景

题目
第二次世界大战期间,英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的两名飞行员,其中一名是英国飞行员,另一名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。

题目描述

一共有 n 个飞行员,其中有 m 个外籍飞行员和 (n−m) 个英国飞行员,外籍飞行员从 1 到 m 编号,英国飞行员从 m+1 到 n 编号。 对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

输入格式

输入的第一行是用空格隔开的两个正整数,分别代表外籍飞行员的个数 m 和飞行员总数 n。
从第二行起到倒数第二行,每行有两个整数 u,v,代表外籍飞行员 u 可以和英国飞行员 v 配合。
输入的最后一行保证为 -1,代表输入结束。

输出格式

本题存在 S p e c i a l J u d g e Special Judge SpecialJudge
请输出能派出最多的飞机数量,并给出一种可行的方案。
输出的第一行是一个整数,代表一次能派出的最多飞机数量,设这个整数是k。
第 2 行到第 k+1 行,每行输出两个整数 u,v,代表在你给出的方案中,外籍飞行员 u 和英国飞行员 v 配合。这 k 行的 u 与 v 应该互不相同。

输入输出样例

输入 #1

5 10
1 7
1 8
2 6
2 9
2 10
3 7
3 8
4 7
4 8
5 10
-1 -1

输出 #1

4
1 7
2 9
3 8
5 10

分析:

匈牙利算法の模板题(???)
看隔壁网络流能做到 0 M S 0MS 0MS 都要馋哭了……
不过我很好奇 不加快读会全 T L E TLE TLE 1.2 S @ e a c h d o t 1.2S@each dot 1.2S@eachdot
加个快读就变成 3 M S @ e a c h d o t ? 3MS@each dot? 3MS@eachdot
最后直接对应输出即可 不是什么变式题 就是二分图の模板……

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define inf 0x7fffffff
#define N 500008
#pragma GCC optimize(2)
using namespace std;
template<typename T>void read(T &a)  //快读
{
    
    
    T x=0,f=1;char ch=getchar();
    while(!isdigit(ch))
    {
    
    
        if(ch=='-')f=0;ch=getchar();
    }
    while(isdigit(ch))
    {
    
    
        x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
    }
    a=f?x:-x;
}
ll n,m,ans,link[N];
struct node{
    
    
    ll to,next; 
}a[N];
ll x,y,tot,head[N];
bool cover[N];
void add(ll x,ll y){
    
    a[++tot]=(node){
    
    y,head[x]};head[x]=tot;}  //邻接表
bool find(ll x)  //匹配函数
{
    
    
    for(register ll i=head[x];i;i=a[i].next)
    {
    
    
        ll qwq=a[i].to;
        if(!cover[qwq])
        {
    
    
            cover[qwq]=1;
            if(!link[qwq]||find(link[qwq]))
            {
    
    
                link[qwq]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    
    
	read(n);read(m);read(x);read(y);
    while(x!=-1&&y!=-1)
    {
    
    
        if(x<=n&&y<=m) add(x,y);  //special judge
        read(x);read(y);
    }
    for(register ll i=1;i<=n;i++)
    {
    
    
        memset(cover,0,sizeof(cover));
        if(find(i)) ans++;
    }
    printf("%d\n",ans);
    for(register ll i=n+1;i<=m;i++)
        if(link[i]) printf("%d %d\n",link[i],i);  //对应输出
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/108267210