洛谷_2756 飞行员配对方案问题

题意

给出n个飞行员,其中有m个外籍的,给出它们的几个匹配关系,求出最多能匹配多少组。

思路

这题可以用二分图的最大匹配,但是这里是网络流的题目,所以我这写的是网络流的。建一个源点连本国的飞行员,汇点连外籍的飞行员,跑一边最大流就求得出答案了。

代码

#include<cstdio>
#define min(a,b) a>b?b:a
#define max(a,b) a>b?a:b
int s,t,m,n,x,y,d,b[101],f[101][101],c[101][101],ans;
int find(int k)
{
    if (k==t) return 1;
    for (int i=0;i<=n+1;i++)
    {
        if (b[i]==-1&&(c[k][i]>f[k][i]||f[i][k]>0))
        {
            b[i]=k;
            if (find(i)) return 1;
        }
    }
    return 0;
}
void add()
{
    d=2147483647;
    int i=t;
    while (i!=s)
    {
        if (c[b[i]][i]>0) d=min(d,c[b[i]][i]-f[b[i]][i]);
        if (c[i][b[i]]>0) d=min(d,f[i][b[i]]);
        i=b[i];
    }
    i=t;
    while (i!=s)
    {
        if (c[b[i]][i]>0) f[b[i]][i]+=d;
        if (c[i][b[i]]>0) f[i][b[i]]-=d;
        i=b[i];
    }
    ans+=d;
}
int main()
{
    scanf("%d%d",&m,&n);
    while (scanf("%d%d",&x,&y),x!=-1||y!=-1) c[x][y]=1;
    s=0;t=n+1;//设源点和汇点
    for (int i=1;i<=m;i++) 
    {
        b[i]=-1;//初始化
        c[s][i]=1;//源点连本国的
    }
    for (int i=m+1;i<=n+1;i++)
    {
        b[i]=-1;
        c[i][t]=1;//连外国的
    }
    b[s]=0;
    while (find(s))//一直找增广路,然后更新流量
    {
        add();
        for (int i=1;i<=n+1;i++)
            b[i]=-1;
    }
    printf("%d\n",ans);//方案数
    for (int i=1;i<=m;i++)
    {
        for (int j=m+1;j<=n;j++)
            if (f[i][j]) {printf("%d %d\n",i,j);break;}//如果这条路之间有流量的话说明它们匹配了
    }
}

猜你喜欢

转载自blog.csdn.net/ssl_hzb/article/details/80745262