Two Sides of the Same Coin --二分图的最大匹配

本文介绍了一种基于二分图的最大匹配算法实现,并通过一个具体的编程问题进行实践。该问题涉及人员技能分配,旨在寻找最佳的团队组合方式,使得团队中成员的技能互补并且排名差为2,最终输出最优组合的数量及具体配对。

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

题意:给定n个人,每个人可能会两种本事,写代码或者测数据,或者都会,还有他的排名,指定分组选择两个人分别会写代码和测数据且排名差距为2,求组合数最大有多少

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int match[1005];
bool vis[1005];
struct Node{
    char name[25];
    int spec;
    int rank;
}lvex[1005];
Node rvex[1005];
bool g[1005][1005];
int ln,rn;
bool dfs(int l){                    //二分图最大匹配
    for(int i=1;i<=rn;i++){
        if(g[l][i]&&!vis[i]){
            vis[i]=1;
            if(match[i]==-1||dfs(match[i])){    //找到增广通路,更新ans+1的匹配边(原来是ans条匹配边)
                match[i]=l;
                return true;
            }
        }
    }
    return false;       //没找到增广通路
}
int fit(){              
    int ans=0;
    memset(match,-1,sizeof(match));
    for(int i=1;i<=ln;i++){
        memset(vis,0,sizeof(vis));
        if(dfs(i)) ans++;
    }
    return ans;
}
int main()
{
    int n;
    char s1[100],s2[100];
    int temp;
    memset(g,0,sizeof(g));
    scanf("%d",&n);
    ln=rn=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%s %s %d",s1,s2,&temp);
        if(temp%4>=2){ //通过%4分成左右两个二分图 
            strcpy(lvex[++ln].name,s1);
            if(strcmp("statements",s2)==0) lvex[ln].spec=1;
            else if(strcmp("testdata",s2)==0) lvex[ln].spec=2;
            else lvex[ln].spec=3;
            lvex[ln].rank=temp;
        }
        else{
            strcpy(rvex[++rn].name,s1);
            if(strcmp("statements",s2)==0) rvex[rn].spec=1;
            else if(strcmp("testdata",s2)==0) rvex[rn].spec=2;
            else rvex[rn].spec=3;
            rvex[rn].rank=temp;
        }
    }
    for(int i=1;i<=ln;i++)
    {
        for(int j=1;j<=rn;j++)
        {
            if((lvex[i].spec!=rvex[j].spec||rvex[j].spec==3||lvex[i].spec==3)&&(lvex[i].rank-rvex[j].rank==2||lvex[i].rank-rvex[j].rank==-2))
            {
                g[i][j]=1;
            }
        }
    }
    printf("%d\n",fit());
    for(int i=1;i<=rn;i++)
    {
        if(match[i]!=-1)
        {
            if(lvex[match[i]].spec==1||(lvex[match[i]].spec==3&&rvex[i].spec==2))
            printf("%s %s\n",lvex[match[i]].name,rvex[i].name);
            else
            printf("%s %s\n",rvex[i].name,lvex[match[i]].name);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值