您的位置:首页 > 其它

洛谷P3386【模板】二分图匹配

2017-08-22 22:35 323 查看
题目背景

二分图

题目描述

给定一个二分图,结点个数分别为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>mv>m 的情况。请把 v>mv>m 的数据自觉过滤掉。

算法:二分图匹配

【题解】

二分图匹配用匈牙利算法或者网络流都可做(ps:能用匈牙利算法做的都能用网络流做),但是效率差别较大。

网络流可达30ms,邻接表匈牙利1440ms,邻接矩阵匈牙利4036ms。

而我只是一个提高组的蒟蒻,没兴趣搞省选级别的网络流。。。就来个邻接表匈牙利算法吧。

(吐槽:为什么大佬的邻接表都有STL和指针,看得好难受。。。)

注意事项:

1、存点的结构体的空间尽量大,我的程序开到了n×n×5。(开n时10个点RE。。。)

2、要去掉u>n和v>m的情况。(但邻接矩阵没必要)

3、程序注释非常重要,有助于理解匈牙利算法精髓,希望大家仔细阅读。

4、邻接表既省时间又省空间,建议多用。

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define fp(i,a,b) for(int i=a;i<=b;i++)
#define fq(i,a,b) for(int i=a;i>=b;i--)
#define il inline
#define re register
#define ll long long
using namespace std;
bool vis[4005]={};
int n,m,k,ans=0,link[4005]={},head[4005]={},cnt=0;//vis用来标记   link记录情侣关系
struct Edge
{
int to,next;
}e[4000005];//e记录有好感
il int gi()
{
int x=0;
short int t=1;
char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if(ch=='-') t=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*t;
}
il bool dfs(int u)//匈牙利算法
{
for(int i=head[u];i;i=e[i].next)//扫描每个妹子,这里已保证有好感
{
int v=e[i].to;
if(!vis[v])//if (单身)
{
vis[v]=1;
if(!link[v]||dfs(link[v])) {link[v]=u;return 1;}//名花无主||者能腾出个位置来,这里使用递归
}
}
return 0;
}
int main()
{
n=gi();m=gi();k=gi();
fp(i,1,k)
{
int u=gi(),v=gi();
if(u>n||v>m) continue;//去掉无效情况
e[++cnt]=(Edge){v,head[u]};head[u]=cnt;//有好感就连条边(标准链式前向星存储)
}
fp(i,1,n)
{
memset(vis,0,sizeof(vis));
if(dfs(i)) ans++;//情侣配成
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分图