#78. 二分图最大匹配

从前一个和谐的班级,有 nlnl 个是男生,有 nrnr 个是女生。编号分别为 1,…,nl1,…,nl 和 1,…,nr1,…,nr。

有若干个这样的条件:第 vv 个男生和第 uu 个女生愿意结为配偶。

请问这个班级里最多产生多少对配偶?

输入格式

第一行三个正整数,nl,nr,mnl,nr,m。

接下来 mm 行,每行两个整数 v,uv,u 表示第 vv 个男生和第 uu 个女生愿意结为配偶。保证 1≤v≤nl1≤v≤nl,1≤u≤nr1≤u≤nr,保证同一个条件不会出现两次。

输出格式

第一行一个整数,表示最多产生多少对配偶。

接下来一行 nlnl 个整数,描述一组最优方案。第 vv 个整数表示 vv 号男生的配偶的编号。如果 vv 号男生没配偶请输出 00。

样例一

input

2 2 3
1 1
1 2
2 1

output

2
2 1

explanation

11 号男生跟 22 号女生幸福地生活在了一起~

22 号男生跟 11 号女生幸福地生活在了一起~

样例二

input

2 2 2
1 1
2 1

output

1
1 0

explanation

班上一个女神一个女汉子,两个男生都去追女神。一种最优方案是:

11 号男生跟 11 号女生幸福地生活在了一起~

22 号男生孤独终生。= =||

限制与约定

1≤nl,nr≤5001≤nl,nr≤500,1≤m≤2500001≤m≤250000。

时间限制:1s1s

空间限制:256MB


这个题目实际上就是二分图匹配的模板题。

--------
这里请允许我狠狠地吐槽《啊哈!算法》《信息学奥赛一本通》一类的野鸡书。语言很通俗,外表看起来很花俏没错,但错漏百出。《啊哈!算法》里面有相当一部分内容是有严重错误的,dijkstra、最小生成树、邻接表、匈牙利算法部分都有问题,甚至是代码问题,模板让你交上去wa成狗。
但我不得不说,上面两本书是适合新手的。
--------
这里用的是匈牙利算法,题目很老实没什么坑点。
注意:边表数组要开到500000以上,因为是无向图,要建两条边。
注意:match[i]存储i的配偶,1-n1是男方;n1+1-n1+n2是女方,结果要输出男方的配偶,也就是结果要输出match[i](1-n1)。
注意:对每一个点进行增广路时要判断那个点的配偶是否已经确认了,也就是判断match[i]是否为0。
注意:对每一个点进行增广路前要把用来标记的数组也就是book数组清0,再book[i]=1;意味着i点访问过了。
注意:输出的时候如果match[i]!=0match[i]要-n1,否则输出0,原因很简单,自己想。

讲讲dfs的代码。

bool dfs(int u)//寻找u节点的配偶
{
  for (int i=head[u]; i; i=edge[i].next) //枚举以u为出点的每一条边
  if (book[edge[i].to]==0) {//如果某个节点还没有访问过
    book[edge[i].to]=1;//标记已访问过
    if (match[edge[i].to]==0||dfs(match[edge[i].to])) {//match[edge[i].to]==0意味着edge[i].to点还没有配偶;如果edge[i].to点有配偶了,就dfs询问edge[i].to点的配偶能不能“让位”去找别的配偶。这里有点小三上位的意思。如果match[edge[i].to]点找到了新的配偶,就会和edge[i].to点离婚,这样子u点就可以和edge[i].to点在一起啦!
      match[edge[i].to]=u;//标记互为配偶
      match[u]=edge[i].to;
      return 1;//找到配偶
    }
  }
  return 0;//没有找到
}

我已经详细地解释了匈牙利代码的主要部分。

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
int read()
{
int x=,f=; char c=getchar();
while (c<''||c>'') {if (c=='-') f=-; c=getchar();}
while (c>=''&&c<='') {x=x*+c-'';c=getchar();}
return x*f;
}
long long sum;
int num_edge,head[],match[],u,v,n1,n2,m;
bool book[];
struct Edge
{
int next;
int to;
}edge[];
void add_edge(int from,int to)
{
edge[++num_edge].next=head[from];
edge[num_edge].to=to;
head[from]=num_edge;
}
bool dfs(int u)
{
for (int i=head[u]; i; i=edge[i].next)
if (book[edge[i].to]==) {
book[edge[i].to]=;
if (match[edge[i].to]==||dfs(match[edge[i].to])) {
match[edge[i].to]=u;
match[u]=edge[i].to;
return ;
}
}
return ;
}
int main()
{
n1=read(); n2=read(); m=read();
for (int i=; i<=m; i++) {
u=read(); v=read()+n1;
add_edge(u,v);
add_edge(v,u);
}
for (int i=; i<=n1+n2; i++) {
for (int j=; j<=n1+n2; j++) book[j]=;
book[i]=;
if (match[i]==&&dfs(i)) sum++;
}
printf("%lld\n",sum);
for (int i=; i<=n1; i++)
if (match[i]!=) printf("%d ",match[i]-n1);
else printf("0 ");
return ;
}

二分图最大匹配

有问题可以直接在评论里面提问,有需要转载的请得到我的允许,否则按侵权处理。


Elena loves NiroBC forever!

二分图最大匹配|UOJ#78|匈牙利算法|边表|Elena的更多相关文章

  1. 【二分图最大匹配】【匈牙利算法】zoj3988 Prime Set

    题意:给你n个正整数,一对和为素数的数为一个合法数对.你选不超过K个合法数对,使得你选的数对涉及到的数的数量最大化.输出这个值. 所有1之间是可以任意两两配对的. 把奇数放在左侧,偶数放在右侧. 考虑 ...

  2. hdu 2444 The Accomodation of Students(二分匹配 匈牙利算法 邻接表实现)

    The Accomodation of Students Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

  3. nyoj 239 月老的难题【匈牙利算法+邻接表】

    月老的难题 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘. 现在,由于一些原因,部分男孩与女孩可能结成幸福 ...

  4. 【二分图】【最大匹配】【匈牙利算法】bzoj1191 [HNOI2006]超级英雄Hero

    裸的最大匹配. #include<cstdio> #include<vector> #include<cstring> using namespace std; v ...

  5. 【二分图】【最大匹配】【匈牙利算法】洛谷 P2071 座位安排 seat.cpp/c/pas

    ∵每个座位可以坐俩人,所以拆点最大匹配. #include<cstdio> #include<vector> #include<cstring> using nam ...

  6. 【二分图】【最大匹配】【匈牙利算法】CODEVS 2776 寻找代表元

    裸的匈牙利,存模板. #include<cstdio> #include<vector> #include<cstring> using namespace std ...

  7. ural 1109,NYOJ 239,匈牙利算法邻接表

    NYOJ 239:http://acm.nyist.net/JudgeOnline/problem.php?pid=239 ural 1109 :http://acm.timus.ru/problem ...

  8. poj - 3041 Asteroids (二分图最大匹配+匈牙利算法)

    http://poj.org/problem?id=3041 在n*n的网格中有K颗小行星,小行星i的位置是(Ri,Ci),现在有一个强有力的武器能够用一发光速将一整行或一整列的小行星轰为灰烬,想要利 ...

  9. poj 3894 System Engineer (二分图最大匹配--匈牙利算法)

    System Engineer Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 507   Accepted: 217 Des ...

随机推荐

  1. no accounts with itunes connect access

    有时候打包上传的时候 会遇见  no accounts with itunes connect access 的报错 原因主要如下: 1. 你没有被开发者管理员加入 itunes connect 权限 ...

  2. xcode9 报错 “Swift Language Version” (SWIFT_VERSION) build setting must be set to a supported value for targets which use Swift

    用xcode编译后会出现这个错误的情况: 1.使用cocopod导入第三方swift包后,swift的包是比较老的swift开发的. 2.用xcode9 打开老的swift(比如swift2.0)的工 ...

  3. C# MD5 加密,解密

    //生成cs文件 public class MD5Help { ///MD5加密 public static string MD5Encrypt(string pToEncrypt, string s ...

  4. android保持服务不休眠(持续运行)以及唤醒屏幕的方法

    假设有这样一个应用场景,一个服务一直在默默的工作(比如即时地获取服务器的消息),即使在屏幕已经因为长时间无操作而关闭,或者用户按了电源键让屏幕关闭,手机进入休眠状态,他必须依然在工作中.一旦从服务器获 ...

  5. 有关Linux下request.getRealPath("/")获取路径的问题

    request.getRealPath("/") 在window获取的是服务器的根目录,结尾包含分隔符, 如E:\apache-tomcat-6.0.29-bak\apache-t ...

  6. 【Spark深入学习 -10】基于spark构建企业级流处理系统

    ----本节内容------- 1.流式处理系统背景 1.1 技术背景 1.2 Spark技术很火 2.流式处理技术介绍 2.1流式处理技术概念 2.2流式处理应用场景 2.3流式处理系统分类 3.流 ...

  7. 【Linux高级驱动】触摸屏驱动的移植

    触摸屏驱动的移植 流程 注意:看框架图 1.添加input.c组件 Device Drivers  ---> Input device support  --->  Generic inp ...

  8. Python3自定义json逐层解析器

    [本文出自天外归云的博客园] 用python3对json内容逐层进行解析,拿中国天气网的接口返回数据测试,代码如下: # -*- coding: utf-8 -*- import operator a ...

  9. Linux嵌入式时区修改

  10. Java知多少(22)方法重载

    在Java中,同一个类中的多个方法可以有相同的名字,只要它们的参数列表不同就可以,这被称为方法重载(method overloading). 参数列表又叫参数签名,包括参数的类型.参数的个数和参数的顺 ...