二分图匹配

匈牙利算法

bool finds(int x) //查找函数
{
    for(int i=1;i<=m;i++)
    {
        if(line[x][i] && !used[i])
        {
            used[i]=1;
            if(nxt[i]==0 || finds(nxt[i]))
            {
                nxt[i]=x;
                return true;
            }
        }
    }
    return false;
}
int match() //匹配函数
{
    int sum=0;
    memset(nxt,0,sizeof(nxt));
    for(int i=1;i<=n;i++)
    {
        memset(used,0,sizeof(used));
        if(finds(i))
            sum++;
    }
    return sum;
}

例题hdu2063
RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了。可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐。但是,每个女孩都有各自的想法,举个例子把,Rabbit只愿意和XHD或PQK做partner,Grass只愿意和linle或LL做partner,PrincessSnow愿意和水域浪子或伪酷儿做partner。考虑到经费问题,boss刘决定只让找到partner的人去坐过山车,其他的人,嘿嘿,就站在下面看着吧。聪明的Acmer,你可以帮忙算算最多有多少对组合可以坐上过山车吗?

Input
输入数据的第一行是三个整数K , M , N,分别表示可能的组合数目,女生的人数,男生的人数。
1<=N 和M<=500.接下来的K行,每行有两个数,分别表示女生Ai愿意和男生Bj做partner。最后一个0结束输入。

Output
对于每组数据,输出一个整数,表示可以坐上过山车的最多组合数。

Sample Input
6 3 3
1 1
1 2
1 3
2 1
2 3
3 1
0

Sample Output
3

题解:
二分图匹配板子题

代码:

	#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#define maexp 1e9+7
#define miexp 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long int LL;
int line[1005][1005];
int used[1005];
int nxt[1005];
int n,m,u,v;
bool finds(int x)
{
    for(int i=1;i<=m;i++)
    {
        if(line[x][i] && !used[i])
        {
            used[i]=1;
            if(nxt[i]==0 || finds(nxt[i]))
            {
                nxt[i]=x;
                return true;
            }
        }
    }
    return false;
}
int match()
{
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        memset(used,0,sizeof(used));
        if(finds(i))
            sum++;
    }
    return sum;
}
int main()
{
    int k;
    while(~scanf("%d",&k))
    {
        if(k==0)
            break;
        scanf("%d%d",&n,&m);
        memset(line,0,sizeof(line));
        memset(nxt,0,sizeof(nxt));
        while(k--)
        {
            scanf("%d%d",&u,&v);
            line[u][v]=1;
        }
        printf("%d\n",match());
    }
    return 0;
}

例题HDU1083 course
题意:N个学生 P 个课程 求最大匹配

3 3 //学生 课程
3 1 2 3 //课程1 匹配学生1 2 3
2 1 2
1 1

题解:匈牙利算法裸题

代码:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#define maexp 1e9+7
#define miexp 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long int LL;
int line[1005][1005];
int used[1005];
int nxt[1005];
int n,m,u,v;
bool finds(int x)
{
    for(int i=1;i<=m;i++)
    {
        if(line[x][i] && !used[i])
        {
            used[i]=1;
            if(nxt[i]==0 || finds(nxt[i]))
            {
                nxt[i]=x;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    int t,i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(line,0,sizeof(line));
        memset(nxt,0,sizeof(nxt));
        for(int i=1;i<=n;i++)
        {
            int u,v;
            scanf("%d",&u);
            for(int j=0;j<u;j++)
            {
                scanf("%d",&v);
                line[i][v]=1;
            }
        }
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            memset(used,0,sizeof(used));
            if(finds(i))
                sum++;
        }
        if(sum==n)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

hihocoder 1122
题目:

Input
第1行:2个正整数,N,M(N表示点数 2≤N≤1,000,M表示边数1≤M≤5,000)
第2…M+1行:每行两个整数u,v,表示一条无向边(u,v)

Output
第1行:1个整数,表示最大匹配数

Sample Input
5 4
3 2
1 3
5 4
1 5
Sample Output
2

题解:
因为是无向图,所以预处理的时候正向反向都要匹配。
因为双向都匹配了,所以最后的结果要除以2.
其他的就是板子。

代码:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#define maexp 1e9+7
#define miexp 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long int LL;
int line[1005][1005];
int used[1005];
int nxt[1005];
int n,m,u,v;
bool finds(int x)
{
    for(int i=1;i<=n;i++)
    {
        if(line[x][i] && !used[i])
        {
            used[i]=1;
            if(nxt[i]==0 || finds(nxt[i]))
            {
                nxt[i]=x;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    int i,j;
    while(~scanf("%d%d",&n,&m)) //n个点,m条边
    {
        memset(line,0,sizeof(line));
        memset(nxt,0,sizeof(nxt));
        for(int i = 1; i <= m; i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			line[u][v] = line[v][u] = 1; //无向图双向处理
		}

        int sum=0;
        for(int i=1;i<=n;i++)
        {
            memset(used,0,sizeof(used));
            if(finds(i))
                sum++;
        }
            printf("%d\n",sum/2); //匹配了两次,所以除以2
    }
    return 0;
}

POJ 3041 Asteroids(匈牙利算法)最小点覆盖
题目:
Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 <= N <= 500). The grid contains K asteroids (1 <= K <= 10,000), which are conveniently located at the lattice points of the grid.

Fortunately, Bessie has a powerful weapon that can vaporize all the asteroids in any given row or column of the grid with a single shot.This weapon is quite expensive, so she wishes to use it sparingly.Given the location of all the asteroids in the field, find the minimum number of shots Bessie needs to fire to eliminate all of the asteroids.
Input

  • Line 1: Two integers N and K, separated by a single space.
  • Lines 2…K+1: Each line contains two space-separated integers R and C (1 <= R, C <= N) denoting the row and column coordinates of an asteroid, respectively.
    Output
  • Line 1: The integer representing the minimum number of times Bessie must shoot.
    Sample Input
    3 4
    1 1
    1 3
    2 2
    3 2
    Sample Output
    2

题意:给出一个n*n的矩阵和矩阵上m个点,问你最少删除了多少行或列之后,点能全部消失。(联想:给出一张图上的m条边的n个相交顶点(xi, yi),问最少用其中的几个点,就可以和所有的边相关联)

题解:
匈牙利算法中的最小点覆盖问题,也是板子。不过不好理解。

代码:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#define maexp 1e9+7
#define miexp 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long int LL;
int line[1005][1005];
int used[1005];
int nxt[1005];
int n,m,u,v,i,j;
bool finds(int x)
{
    for(int i=1;i<=m;i++)
    {
        if(line[x][i] && !used[i])
        {
            used[i]=1;
            if(nxt[i]==0 || finds(nxt[i]))
            {
                nxt[i]=x;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    while(~scanf("%d%d",&m,&n))
    {
        memset(line,0,sizeof(line));
        memset(nxt,0,sizeof(nxt));
        for(i=0;i<n;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			line[u][v] = 1;
		}

        int sum=0;
        for(int i=1;i<=m;i++)
        {
            memset(used,0,sizeof(used));
            if(finds(i))
                sum++;
        }
            printf("%d\n",sum);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值