【二分图】P3386洛谷模板

题目背景

二分图

题目描述

给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数

输入输出格式

输入格式:

 

第一行,n,m,e

第二至e+1行,每行两个正整数u,v,表示u,v有一条连边

 

输出格式:

 

共一行,二分图最大匹配

 

输入输出样例

输入样例#1:
1 1 1
1 1
输出样例#1:
1

说明

n,m<=1000,1<=u<=n,1<=v<=m

因为数据有坑,可能会遇到v>m的情况。请把v>m的数据自觉过滤掉。

算法:二分图匹配

 

题解

想必大家都看到了说明的数据有坑了吧。。。

所以邻接表或邻接矩阵加匈牙利算法吧。。。

就是要加一条判断。。。

代码如下:

邻接矩阵:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int n,m,k,x,y,ans;
bool map[1001][1001],used[1001];
int point[1001];

bool find(int a)
{
    for(int i=0;i<=m;++i)
    {
        if(!used[i]&&map[a][i])
        {
            used[i]=1;
            if(point[i]==0||find(point[i]))
            {
                point[i]=a;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=k;++i)
    {
        scanf("%d%d",&x,&y);
        if(x>m||y>m)continue;
        map[x][y]=1;
    }
    for(int i=1;i<=n;++i)
    {
        memset(used,0,sizeof(used));
        if(find(i))ans++;
    }
    printf("%d",ans);
}

 邻接表:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

struct edge{
    int y,ne;
}e[1000001];

int n,m,x,y,k,ans,ecnt;
int head[2010],point[2010];
bool used[2010];

void add(int a,int b)
{
    e[++ecnt].y=b;
    e[ecnt].ne=head[a];
    head[a]=ecnt;
}

bool find(int a)
{
    for(int i=head[a];i;i=e[i].ne)
    {
        if(!used[e[i].y])
        {
            used[e[i].y]=1;
            if(point[e[i].y]==0||find(point[e[i].y]))
            {
                point[e[i].y]=a;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=k;++i)
    {
        scanf("%d%d",&x,&y);
        if(y<=m&&x<=m)
        {
            add(x,y);
        }
    }
    for(int i=1;i<=n;++i)
    {
        memset(used,0,sizeof(used));
        if(find(i))ans++;
    }
    printf("%d",ans);
}

 

posted @ 2017-05-11 18:57  减维  阅读(152)  评论(0编辑  收藏  举报