二分匹配(匈牙利算法)

  • 概念什么的网上搜一下就好了,这里我就放个模板和题目吧。
  • 注意:这里是寻找最大匹配
  • 模板:
int path(int x)
{
    for(int y=1; y<=n; y++)
    {
        if(mat[x][y] && !vis[y])
        {
            vis[y]=1;
            if(cy[y]==-1 || path(cy[y]))//这里是用递归
            {
                cx[x]=y;
                cy[y]=x;
                return 1;
            }
        }
    }
    return 0;
}
int maxmatch()
{
    int res=0;
    memset(cx, -1, sizeof(cx));
    memset(cy, -1, sizeof(cy));
    for(int i=1; i<=n; i++)
    {
        if(cx[i]==-1)
        {
            memset(vis, 0, sizeof(vis));//vis数组每一次都要初始化
            res+=path(i);
        }
    }
    return res;//输出最大匹配数
}

其实这其中的递归我没有完全搞清楚,可以参考
http://blog.csdn.net/dark_scope/article/details/8880547中的描述。
(貌似需要学习最大流算法)

poj3041

  • 这里尽管知道了是用这个算法来做,但一开始还是没有思路,看了题解后发现可以将点的坐标转化为二分图的一条边,这样就可以做了(自己应该是怎么都想不到吧)

hdu5943

  • 一开始以为是数学题,还是自己太天真。

Problem Description
There is a kindom of obsession, so people in this kingdom do things very strictly.
They name themselves in integer, and there are n people with their id continuous (s+1,s+2,⋯,s+n) standing in a line in arbitrary order, be more obsessively, people with id x wants to stand at yth position which satisfy
xmody=0
Is there any way to satisfy everyone’s requirement?
Input
First line contains an integer T, which indicates the number of test cases.
Every test case contains one line with two integers n, s.
Limits
1≤T≤100.
1≤n≤109.
0≤s≤109.
Output
For every test case, you should output ‘Case #x: y’, where x indicates the case number and counts from 1 and y is the result string.
If there is any way to satisfy everyone’s requirement, y equals ‘Yes’, otherwise y equals ‘No’.
Sample Input
2
5 14
4 11
Sample Output
Case #1: No
Case #2: Yes

代码:

#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=810;
int n, s;
int mat[maxn][maxn], vis[maxn], cx[maxn], cy[maxn];

int path(int x)
{
    for(int y=1; y<=n; y++)
    {
        if(mat[x][y] && !vis[y])
        {
            vis[y]=1;
            if(cy[y]==-1 || path(cy[y]))
            {
                cx[x]=y;
                cy[y]=x;
                return 1;
            }
        }
    }
    return 0;
}
int maxmatch()
{
    int res=0;
    memset(cx, -1, sizeof(cx));
    memset(cy, -1, sizeof(cy));
    for(int i=1; i<=n; i++)
    {
        if(cx[i]==-1)
        {
            memset(vis, 0, sizeof(vis));
            res+=path(i);
        }
    }
    return res;
}
int main()
{
    int T;
    scanf("%d", &T);
    for(int test=1; test<=T; test++)
    {
        scanf("%d %d", &n, &s);
        if(n>=s){int t=n; n=s; s=t;}//原来想过当两个素数出现时是不可能匹配成功的,但其实是有可能的(当两组数中有数重合时),因此这里去掉重合的部分
        if(n>=800){printf("Case #%d: No\n", test); continue;}
        memset(mat, 0, sizeof(mat));
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
                if((s+i)%j==0)mat[i][j]=1;
        }
        int num=maxmatch();
        if(num==n)printf("Case #%d: Yes\n", test);
        else printf("Case #%d: No\n", test);
    }
    return 0;
}
  • 我的感受是能想到用二分匹配去做题才是更难的部分= =
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值