使用最大流和费用流解决二分图的多重匹配

之前编辑的忘存了好气啊。。

本来打算学完二分图的乱七八糟的匹配之后再去接触网络流的,提前撞到了

之前我们说的二分图最大匹配和二分图最大权匹配有一个特点,那就是没个点只能与一条边相匹配

如果规定一个点要与L条边相匹配,这样的问题就是二分图的多重匹配问题

然后根据边是否带权重,又可以分为二分图最大多重匹配和二分图最大权多重匹配(二分图多重最佳完美匹配)

首先给出二分图多重最大匹配的做法:

在原图上建立源点S和汇点T,S向每个X方点连一条容量为该X方点L值的边,每个Y方点向T连一条容量为该Y方点L值的边

原来二分图中各边在新的网络中仍存在,容量为1(若该边可以使用多次则容量大于1),求该网络的最大流,就是该二分图多重最大匹配的值

然后给出二分图多重最优匹配(二分图多重最大权匹配)的做法:

在原图上建立源点S和汇点T,S向每个X方点连一条容量为该X方点L值、费用为0的边,每个Y方点向T连一条容量为该Y方点L值、费用为0的边

原来二分图中各边在新的网络中仍存在,容量为1(若该边可以使用多次则容量大于1),费用为该边的权值。求该网络的最大费用最大流,就是该二分图多重最优匹配的值

这道题里面,一共有X方点这么多的电影,每个电影需要拍摄多少天就是对应的X方点L值,然后每一天是一个Y方点,由于每一天只能拍摄一部电影,所有Y方点的L值均为1

下面介绍一下实现:

int n,sum,cnt,ans;
int g[maxn],cur[maxn];
int str[25][10];
struct Edge{int u,v,next,cap,flow;}e[maxm];

这里面的cur数组是g数组的临时数组

str用来保存每一个电影可以在哪一天拍摄

Edge是网络流图里面的边

void addedge(int u,int v,int c)
{e[++cnt].u=u;e[cnt].v=v;e[cnt].cap=c;e[cnt].flow=0;e[cnt].next=g[u];g[u]=cnt;e[++cnt].u=v;e[cnt].v=u;e[cnt].cap=0;e[cnt].flow=0;e[cnt].next=g[v];g[v]=cnt;
}

建图的时候,注意怎么赋值的

接下来根据题意建图:

for(int i=1;i<=n;i++){for(int j=1;j<=7;j++)scanf("%d",&str[i][j]);    scanf("%d%d",&d,&w);sum+=d;addedge(0,i,d);  //容量为需要多少天 for(int j=1;j<=7;j++)for(int k=0;k<w;k++)if(str[i][j]) addedge(i,20+k*7+j,1);}for(int i=21;i<=370;i++) addedge(i,371,1);ans=maxflow(0,371);

0为源点,371为汇点

sum最后进行一个统计,和源点出发的最大流量进行比较,如果相等,说明电影排的开

然后是求最大流的一个板子

int maxflow(int st,int ed)
{int flowsum=0;while(bfs(st,ed)){memcpy(cur,g,sizeof(g));flowsum+=dfs(st,ed,INF);//cout<<"#"<<flowsum<<" ";
    }return flowsum;}

具体的DFS和BFS这里不作为重点,以后再说

下面给出完整的实现:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int INF=1000000000;
  6 const int maxn=1005;
  7 const int maxm=20005;
  8 int n,sum,cnt,ans;
  9 int g[maxn],cur[maxn];
 10 int str[25][10];
 11 struct Edge{int u,v,next,cap,flow;}e[maxm];
 12 void addedge(int u,int v,int c)
 13 {
 14     e[++cnt].u=u;e[cnt].v=v;e[cnt].cap=c;
 15     e[cnt].flow=0;e[cnt].next=g[u];g[u]=cnt;
 16
 17     e[++cnt].u=v;e[cnt].v=u;e[cnt].cap=0;
 18     e[cnt].flow=0;e[cnt].next=g[v];g[v]=cnt;
 19 }
 20 int q[maxn],vis[maxn],d[maxn];
 21 bool bfs(int st,int ed)
 22 {
 23     memset(q,0,sizeof(q));
 24     memset(vis,0,sizeof(vis));
 25     memset(d,-1,sizeof(d));
 26     vis[st]=1;d[st]=0;
 27     int h=0,t=1;
 28     q[t]=st;
 29     while(h!=t)
 30     {
 31         h=h%maxn+1;
 32         int u=q[h];
 33         for(int tmp=g[u];tmp;tmp=e[tmp].next)
 34         {
 35             if(!vis[e[tmp].v]&&e[tmp].cap>e[tmp].flow)
 36             {
 37                 vis[e[tmp].v]=1;
 38                 d[e[tmp].v]=d[u]+1;
 39                 if(e[tmp].v==ed) return true;
 40                 t=t%maxn+1;
 41                 q[t]=e[tmp].v;
 42             }
 43         }
 44     }
 45     return false;
 46 }
 47 int getpair(int x)
 48 {
 49     if(x%2==0)
 50         return x-1;
 51     else return x+1;
 52 }
 53 int dfs(int x,int ed,int a)
 54 {
 55     if(x==ed||a==0) return a;
 56     int flow=0,f;
 57     for(int tmp=cur[x];tmp;tmp=e[tmp].next)
 58     {
 59         if(d[e[tmp].v]==d[x]+1&&(f=dfs(e[tmp].v,ed,min(a,e[tmp].cap-e[tmp].flow)))>0)
 60         {
 61             e[tmp].flow+=f;
 62             e[getpair(tmp)].flow-=f;
 63             a-=f;
 64             flow+=f;
 65             if(a==0) break;
 66         }
 67     }
 68     return flow;
 69 }
 70 int maxflow(int st,int ed)
 71 {
 72     int flowsum=0;
 73     while(bfs(st,ed))
 74     {
 75         memcpy(cur,g,sizeof(g));
 76         flowsum+=dfs(st,ed,INF);
 77         //cout<<"#"<<flowsum<<" ";
 78     }
 79     return flowsum;
 80
 81 }
 82 void init()
 83 {
 84     sum=cnt=0;
 85     memset(g,0,sizeof(g));
 86 }
 87 int main()
 88 {
 89     int T,d,w;
 90     scanf("%d",&T);
 91     while(T--)
 92     {
 93         init();
 94         scanf("%d",&n);
 95         for(int i=1;i<=n;i++)
 96         {
 97             for(int j=1;j<=7;j++)
 98                 scanf("%d",&str[i][j]);
 99             scanf("%d%d",&d,&w);
100             sum+=d;
101             addedge(0,i,d);  //容量为需要多少天
102             for(int j=1;j<=7;j++)
103                 for(int k=0;k<w;k++)
104                     if(str[i][j]) addedge(i,20+k*7+j,1);
105         }
106         for(int i=21;i<=370;i++) addedge(i,371,1);
107         ans=maxflow(0,371);
108         if(ans==sum) printf("Yes\n");
109         else printf("No\n");
110     }
111     return 0;
112 }

据说这是典型的最大流题目,然而为了强行安利一波二分图的多重匹配,就不说成那个了

转载于:https://www.cnblogs.com/aininot260/p/9441001.html

图论:二分图多重匹配相关推荐

  1. 【网络流24题】解题报告:E 、圆桌问题(最大流求二分图多重匹配)

    E .圆桌问题(最大流求二分图多重匹配)[省选/NOI- ] 可以直观的想到,二分图的左边是单位,右边是桌子 由于题目的限制 每个单位只能在一个桌子坐一个人 所以我们就把每个单位向各个桌子连一道流量为 ...

  2. poj2112(floyd+二分+二分图多重匹配)

    (感觉是一个比较基础的二分图多重匹配) 题目意思大概就是有K个挤奶点,C个奶牛,一个挤奶点能容下M个奶牛,问如果所有奶牛都被放入挤奶点时,距离最远奶牛得最短距离(距离可以经过其他点) 首先看到可以经过 ...

  3. 网络流三·二分图多重匹配 HihoCoder - 1393

    网络流三·二分图多重匹配 HihoCoder - 1393 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int ma ...

  4. POJ - 3189 Steady Cow Assignment(二分图多重匹配)

    题目链接:点击查看 题目大意:给出n只奶牛以及m个牛棚,接下来给出一个n*m的矩阵,给出每一只奶牛对于每个牛棚的喜爱度,按照降序给出,从rank1到rankm,现在问如何分配牛棚能让所有奶牛中最高的r ...

  5. HDU - 3605 Escape(二分图多重匹配-网络流最大流+思维建边+状态压缩)

    题目链接:点击查看 题目大意:到世界末日了,现在人们要逃离去其他的星球,现在给出n个人以及m个星球,再给出每个人可以前往的星球,最后给出每个星球的容量,题目问最多能让多少个人逃离 题目分析:这个题读完 ...

  6. 【网络流24题】No.7 试题库问题 (最大流,二分图多重匹配)

    [题意] 假设一个试题库中有 n 道试题. 每道试题都标明了所属类别. 同一道题可能有多个类别属性.现要从题库中抽取 m 道题组成试卷.并要求试卷包含指定类型的试题. 试设计一个 满足要求的组卷算法. ...

  7. 网络流三·二分图多重匹配

    描述 学校的秋季运动会即将开始,为了决定参赛人员,需要统计分配比赛选手. 已知班级一共有N名学生,编号依次为1..N. 运动会一共有M项不同的比赛,编号为1..M.第i项比赛每个班需要派出m[i]名选 ...

  8. POJ - 2289 Jamie's Contact Groups(二分图多重匹配)

    题目链接:点击查看 题目大意:给出n个联系人,以及m个分组,现在需要将n个联系人分到m个分组中,需要满足让人数最多的组的人数最少,输出这个值 题目分析:因为是让最大值最小,所以肯定是要用二分解决,因为 ...

  9. [tyvj1935 Poetize3]导弹防御塔 (二分图多重匹配)

    传送门 Description Freda控制着N座可以发射导弹的防御塔.每座塔都有足够数量的导弹,但是每座塔每次只能发射一枚.在发射导弹时,导弹需要T1秒才能从防御塔中射出,而在发射导弹后,发射这枚 ...

最新文章

  1. 微生物生态学相关期刊2022年实时影响因子
  2. 复制活动记录记录的最简单方法是什么?
  3. C#编程利器之四:委托与事件(Delegate and event) (上)
  4. 移动医疗APP(解决方案)下载
  5. [yum]Another app is currently holding the yum lock
  6. 2.看板方法---什么是看板方法
  7. hdu acm 1016
  8. mysql 分库外置索引,MySQL的分库分表与Innodb的Btree索引
  9. linux sigar 进程监控,Linux 下使用Sigar 获取CPU 使用率
  10. 5个免费商用音频素材网站
  11. [美] 尼古拉斯·卡尔 《浅薄:互联网如何毒化了我们的大脑 》
  12. “企业上云”计划出炉,三年内河北万家企业要上云!|中机智库
  13. 西安python培训价格
  14. 15 | 浮点数和定点数(上):怎么用有限的Bit表示尽可能多的信息?
  15. 世界五百强企业网站(二)
  16. 矩阵分析与应用学习笔记1
  17. 论文略读 | Pattern-revising Enhanced Simple Question Answering over Knowledge Bases
  18. vue14 动画-自学视频
  19. js 获取本月第一天和最后一天,上月第一天和最后一天
  20. net6 winform应用读取配置文件(依赖注入、普通读取)

热门文章

  1. SpringCloud Config手动刷新及自动刷新
  2. (原創) Verilog入門書推薦2:數位系統實習 Quartus II (SOC) (Verilog)
  3. MySQL:浅析 Impossible WHERE noticed after reading const tables
  4. 无人机成为黑客的新工具,可黑掉部分家用的智能设备
  5. 值得学习的C/C++开源框架(转)
  6. [NOI2014]魔法森林
  7. 译 | 像使用一台主机一样管理集群
  8. long long _int64使用总结
  9. lisp 标注螺纹孔_螺纹的表示法和标注
  10. .set伪指令(mips)