二分匹配(匈牙利算法)

来源:互联网 发布:阿里云香港空间怎么样 编辑:程序博客网 时间:2024/06/02 03:35
  • 概念什么的网上搜一下就好了,这里我就放个模板和题目吧。
  • 注意:这里是寻找最大匹配
  • 模板:
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
原创粉丝点击