#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. 用 JAAS 和 JSSE 实现 Java 安全性

    JAAS 和 JSSE 概述 JAAS 提供了一种灵活的.说明性的机制,用于对用户进行认证并验证他们访问安全资源的能力.JSSE 定义了通过安全套接字层(SSL)进行安全 Web 通信的一种全 Jav ...

  2. iOS APP 安全测试

    1.ipa包加壳 首先,我们可以通过iTunes 下载 AppStore的ipa文件(苹果 把开发者上传的ipa包 进行了加壳再放到AppStore中),所以我们从AppStore下载的ipa都是加壳 ...

  3. 【Visual Studio】Visual Studio对CLR异常的特殊支持

    Visual Studio 对异常进行了特殊的支持,它能够在进行了特殊设置后,使代码中的try catch块失效.也就是说,一个异常在正常情况下应该能够被某个特殊的try catch块捕获,但是Vis ...

  4. JVM源码分析之Object.wait/notify实现(转载)

    最简单的东西,往往包含了最复杂的实现,因为需要为上层的存在提供一个稳定的基础,Object作为java中所有对象的基类,其存在的价值不言而喻,其中wait和notify方法的实现多线程协作提供了保证. ...

  5. Xilinx 常用模块汇总(verilog)【04】

    作者:桂. 时间:2018-05-15  13:07:02 链接:http://www.cnblogs.com/xingshansi/p/9040472.html 前言 Xilinx 常用模块汇总(v ...

  6. 拯救安卓手机的数据(无法进入系统只能打开recovery)

    这里不得不赞一个谷歌的开放,如果不是这样读取数据就很糟糕了,记得一千带着我的mac本子到苹果店,那个所谓的“天才”就说苹果的数据无法读取,我了个艹,为了避免丢失你必须得准备一个TM.好了废话不多说,进 ...

  7. 【R作图】蜜蜂群图beeswarm和jitter的使用

    最近经常要画好看的盒形图,还要在上面加入散点,所以总结了两个方法. 第一种方法是,利用beeswarm函数: library(beeswarm) beeswarm 蜜蜂群图 http://rgm3.l ...

  8. STM32 ADC 采样 频率的确定

    一 STM32 ADC 采样频率的确定 1.       : 先看一些资料,确定一下ADC 的时钟: (1),由时钟控制器提供的ADCCLK 时钟和PCLK2(APB2 时钟)同步.CLK 控制器为A ...

  9. 关于Stm32定时器+ADC+DMA进行AD采样的实现

    Stm32的ADC有DMA功能这都毋庸置疑,也是我们用的最多的!然而,如果我们要对一个信号(比如脉搏信号)进行定时采样(也就是隔一段时间,比如说2ms),有三种方法: 1.使用定时器中断每隔一定时间进 ...

  10. Go Revel - Cache(缓存)

    revel在服务器端提供了`cache`库用以低延迟的存储临时数据.它缓存那些需要经常访问数据库但是变化不频繁的数据,也可以实现用户会话的存储. ##有效期 一下三种方法为缓存元素设置过期时间: 1. ...