二分图的多重匹配问题不同于普通的最大匹配中的“每个点只能有最多一条边” 而是“每个点连接的边数不超过自己的限定数量”

最大匹配所解决的问题一般是“每个人都有一群想加入的团体 并且一个团体只能收一个人 问有多少人可以加入一个自己喜欢的团体”

而多重匹配是 “每个人都有一群想加入的团体 每个团体可以收给定的人数 问有多少人可以加入一个自己喜欢的团体”

解决这个问题 目前看貌似有三个办法

1 拆点 一个团体可以招x个人 就把它拆成x个只能招一个人的团体 进行最大匹配

2 网络流 s -> 人 cap : 1       人 -> 自己想加的团体 cap : 1     每个团体 -> t cap : 这个团体的容纳人数

3 改一改 xyl的形式 过去我们写linker[]来记录 每个团体的招人情况

现在我们创造一个数组 记录这个团体 能招多少人 现招多少人 招人的情况 这个网址讲的很简单 http://wenku.baidu.com/view/60b301c00c22590102029db2.html

专题里面的这三道题都差不多 都是用二分求一个最大最小值

M poj2289

模板题 需要做一个字符串处理

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<string>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define L long long
int n , m ;
char s[1050];
struct node{
int many ;
int pp[1050];
int cnt ;
}linker[505];
bool vis[505]; vector<int >q[1050]; bool fin(int u){
for(int i = 0 ; i< q[u].size() ; i ++ ){
int v = q[u][i];
if(vis[v]){
vis[v] = false ;
if(linker[v].cnt < linker[v].many) {
linker[v].pp[++linker[v].cnt] = u ;
return true ;
}
else {
for(int j = 1; j <= linker[v].many ;j ++ ){
if(fin(linker[v].pp[j])) {
linker[v].pp[j] = u ;
return true ;
}
}
}
}
}
return false ;
}
bool xyl(int many) {
int res = 0 ;
for(int i = 0 ; i < m ; i ++) {
linker[i].many = many ;
linker[i].cnt = 0 ;
}
for(int i = 1 ; i <= n ; i ++ ){
memset(vis , true , sizeof(vis )) ;
if(fin(i)){
res ++ ;
}
}
return (res == n) ;
}
int main(){
while(scanf("%d%d\n",&n,&m)!=EOF){
if(n == 0 && m == 0)break;
for(int i = 1; i<= n ; i ++)q[i].clear() ;
for(int i = 1; i<= n ; i ++ ){
gets(s) ;
int len = strlen(s);
int j ;
for(j = 0 ; j < len ;j ++ ){
if(s[j] == ' '){
j ++ ;
break ;
}
}
int res = 0;
for( ; j < len ; j ++ ){
if(s[j ] == ' '){
q[i].push_back(res );
res = 0 ;
}
else {
res *= 10 ;
res += ( s[j] - '0' );
}
}
q[i].push_back(res);
res = 0; }
int ans = -1 ;
int l = 1 ;
int r = 1010;
while(l <= r){
int mid = (l + r) / 2 ;
if(xyl(mid)){
ans = mid ;
r = mid - 1 ;
}
else {
l = mid + 1 ;
}
}
printf("%d\n",ans);
}
}

N poj2112

画风突然不对了 细节很多

1 给出的邻接矩阵形式 并不是最短距离 而是类似于 给出一群路来 连接每一个地点

2 给出的 0 代表这两个地点没有路

需要二分一下最大距离

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<string>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define L long long
int n , a , b , m ;
struct node{
int many ;
int pp[300];
int cnt ;
}linker[300];
bool vis[300];
int c[300][300]; bool fin(int u , int jl){
for(int v = 1; v <= a ; v ++ ){
if(c[u][v] > jl || c[u][v] == 0){
continue ;
}
if(vis[v]){
vis[v] = false ;
if(linker[v].cnt < linker[v].many){
linker[v].pp[++linker[v].cnt] = u ;
return true ;
}
else {
for(int j = 1 ; j <= linker[v].many ; j ++ ){
if(fin(linker[v].pp[j] , jl)){
linker[v].pp[j] = u ;
return true ;
}
}
}
}
}
return false ;
}
bool xyl(int jl){
int res = 0 ;
for(int i = 1; i <= a ;i ++){
linker[i].cnt = 0 ;
linker[i].many = m ;
}
for(int i = a + 1 ; i <= n ; i ++ ){
memset(vis , true , sizeof(vis)) ;
if(fin(i , jl)){
res ++ ;
}
}
return (res == b) ;
}
int main(){
while(scanf("%d%d%d",&a , &b , & m)!= EOF){
n = a + b;
for(int i = 1; i <= n ; i ++ ){
for(int j = 1 ; j <= n ; j ++ ){
scanf("%d" , &c[i][j]) ;
}
}
for(int i = 1 ; i <= n ; i ++ ){
for(int j = 1 ; j <= n; j ++ ){
for(int k = 1; k <= n ; k ++ ){
if(i == j || i == k || k == j)continue;
if(c[j][i] != 0 && c[i][k] != 0){
if(c[j][k] > 0)
c[j][k] = min(c[j][i] + c[i][k] , c[j][k]) ;
else {
c[j][k] = c[j][i] + c[i][k] ;
}
}
}
}
}
int l = 1 ;
int r = 999999999 ;
int ans = -1 ;
while(l <= r){
int mid = (l + r) / 2 ;
if(xyl(mid)){
ans = mid ;
r = mid - 1 ;
}
else {
l = mid + 1 ;
}
}
printf("%d\n",ans) ;
}
}

O poj3189

比较考验读题能力...

题意是 给出每头牛对每个谷仓的loverank

求出一个最小的范围 让每头牛最后分配的谷仓的loverank都在这个大小范围内

所以二分范围 枚举起点

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<string>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define L long long
int n , b ;
struct node{
int many ;
int pp[1050];
int cnt ;
}linker[25];
bool vis[25];
int many[25];
int c[1050][25] ; bool fin(int u , int jl , int st){
for(int i = st; i <= st + jl - 1; i ++ ){
int v = c[u][i] ;
if(vis[v]) {
vis[v] = false ;
if(linker[v].cnt < linker[v].many) {
linker[v].pp[++linker[v].cnt] = u ;
return true ;
}
else {
for(int j = 1 ; j <= linker[v].many ; j ++ ){
if(fin(linker[v].pp[j] , jl , st)){
linker[v].pp[j] = u ;
return true ;
}
}
}
}
}
return false ;
}
bool xyl(int jl , int st){
int res = 0 ;
for(int i = 1; i <= b ;i ++ ){
linker[i].cnt = 0;
linker[i].many = many[i] ;
}
for(int i = 1 ; i <= n ; i ++ ){
memset(vis , true , sizeof(vis)) ;
if(fin(i , jl , st)){
res ++ ;
}
}
return (res == n) ;
}
int main(){
while(scanf("%d%d",&n , &b)!=EOF){
for(int i = 1; i<= n ; i ++ ){
for(int j = 1 ; j <= b ;j ++ ){
scanf("%d" , &c[i][j]) ;
}
}
for(int i = 1; i<= b ; i ++ ){
scanf("%d" , &many[i]) ;
}
int l = 1;
int r = b ;
int ans = -1 ;
while(l <= r){
int mid = (l + r) / 2 ;
int i ;
for(i = 1; i + mid - 1 <= b ; i ++ ){
if(xyl(mid , i)){
ans = mid ;
r = mid - 1 ;
break ;
}
}
if(i + mid - 1 > b){
l = mid + 1 ;
}
}
printf("%d\n",ans) ;
}
}

可以看到Dinic跑多重匹配和跑最大匹配 都是一样的写法 只是cap不同

看起来的话 拆点法和xyl的时间复杂度都是很高的 .. Dinic不错的样子

看起来 小虎的担子 又重了一分

[kuangbin带你飞]专题十 匹配问题 二分图多重匹配的更多相关文章

  1. [kuangbin带你飞]专题十 匹配问题

        A-L 二分匹配 M-O 二分图多重匹配 P-Q 二分图最大权匹配 R-S 一般图匹配带花树 模板请自己找     ID Origin Title   61 / 72 Problem A HD ...

  2. [kuangbin带你飞]专题十 匹配问题 一般图匹配

    过去做的都是二分图匹配 即 同一个集合里的点 互相不联通 但是如果延伸到一般图上去 求一个一般图的最大匹配 就要用带花树来解决 带花树模板 用来处理一个无向图上的最大匹配 看了一会还是不懂  抄了一遍 ...

  3. [kuangbin带你飞]专题十 匹配问题 二分匹配部分

    刚回到家 开了二分匹配专题 手握xyl模板 奋力写写写 终于写完了一群模板题 A hdu1045 对这个图进行 行列的重写 给每个位置赋予新的行列 使不能相互打到的位置 拥有不同的行与列 然后左行右列 ...

  4. [kuangbin带你飞]专题十 匹配问题 二分图最大权匹配

    二分图最大权匹配有km算法和网络流算法 km算法模板默认解决最大权匹配的问题 而使用最小费用最大流 是解决最小权匹配问题 这两种办法都可以求最大最小权 需要两次取反 TAT 感觉讲km会很难的样子.. ...

  5. [kuangbin带你飞]专题十五 数位DP

            ID Origin Title   62 / 175 Problem A CodeForces 55D Beautiful numbers   30 / 84 Problem B HD ...

  6. [kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher 题解报告

    来刷kuangbin字符串了,字符串处理在ACM中是很重要的,一般比赛都会都1——2道有关字符串处理的题目,而且不会很难的那种,大多数时候都是用到一些KMP的性质或者找规律. 点击标题可跳转至VJ比赛 ...

  7. [kuangbin带你飞]专题十四 数论基础

            ID Origin Title   111 / 423 Problem A LightOJ 1370 Bi-shoe and Phi-shoe   21 / 74 Problem B ...

  8. 【算法系列学习】DP和滚动数组 [kuangbin带你飞]专题十二 基础DP1 A - Max Sum Plus Plus

    A - Max Sum Plus Plus https://vjudge.net/contest/68966#problem/A http://www.cnblogs.com/kuangbin/arc ...

  9. [kuangbin带你飞]专题十二 基础DP1

            ID Origin Title   167 / 465 Problem A HDU 1024 Max Sum Plus Plus   234 / 372 Problem B HDU 1 ...

随机推荐

  1. 逻辑回归:使用SGD(Stochastic Gradient Descent)进行大规模机器学习

    Mahout学习算法训练模型 mahout提供了许多分类算法,但许多被设计来处理非常大的数据集,因此可能会有点麻烦.另一方面,有些很容易上手,因为,虽然依然可扩展性,它们具有低开销小的数据集.这样一个 ...

  2. C++ trivial和non-trivial构造函数及POD类型(转)

    原博客地址http://blog.csdn.net/a627088424/article/details/48595525 最近正纠结这个问题就转过来了,做了点补充(参考<深度探索C++对象模型 ...

  3. Android Studio中JNI -- 2 -- 编写c文件

    继上一篇,我们在native接口中编写了2个方法 生成的相应.h文件 这时,需要我们自己去完善.c文件 /* DO NOT EDIT THIS FILE - it is machine generat ...

  4. [设计模式]解释器(Interpreter)之大胆向MM示爱吧

    为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 “我刚写了个小程序,需要你来参与下.”我把MM叫到我的电脑旁,“来把下面这条命令打进去,这是个练习打(Pian)符(ni)号(de)的 ...

  5. ecshop---京东手机模板js的eval产生冲突的解决方法。

    今天弄ecshop手机模板的时候,发现首页的广告图出不来,js报错

  6. js 中特殊形势的函数-匿名函数的应用

    javascript中的匿名函数,那什么叫做匿名函数? 匿名函数就是没有函数名称:演示代码: <script> function(x,y){ return x+y //这个就是一个匿名函数 ...

  7. frameset标签代码实现网站跳转

    js代码1: document.writeln("<frameset rows=\"0, *\">"); document.writeln(&quo ...

  8. Python3.4使用MySql

    如何在Django1.6结合Python3.4版本中使用MySql django默认的mysql连接是Mysqldb,悲催的是此版本只支持到python2.7,oracle官方的mysql-conne ...

  9. MyEclipse10

    1.配置tomcat Windows->Preferences->My Eclipse->Servers->Tomcat,对于64位操作系统而言,Tomcat home dir ...

  10. 使用OPCDAAuto.dll编写C# OPC采集程序

    在一台新机器上运行使用OPC自动化接口编写的C#程序报错如下: 索 COM 类工厂中 CLSID 为 {28E68F9A-8D75-11D1-8DC3-3C302A000000} 的组件失败,原因是出 ...