图论:二分图多重匹配
使用最大流和费用流解决二分图的多重匹配
之前编辑的忘存了好气啊。。
本来打算学完二分图的乱七八糟的匹配之后再去接触网络流的,提前撞到了
之前我们说的二分图最大匹配和二分图最大权匹配有一个特点,那就是没个点只能与一条边相匹配
如果规定一个点要与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
图论:二分图多重匹配相关推荐
- 【网络流24题】解题报告:E 、圆桌问题(最大流求二分图多重匹配)
E .圆桌问题(最大流求二分图多重匹配)[省选/NOI- ] 可以直观的想到,二分图的左边是单位,右边是桌子 由于题目的限制 每个单位只能在一个桌子坐一个人 所以我们就把每个单位向各个桌子连一道流量为 ...
- poj2112(floyd+二分+二分图多重匹配)
(感觉是一个比较基础的二分图多重匹配) 题目意思大概就是有K个挤奶点,C个奶牛,一个挤奶点能容下M个奶牛,问如果所有奶牛都被放入挤奶点时,距离最远奶牛得最短距离(距离可以经过其他点) 首先看到可以经过 ...
- 网络流三·二分图多重匹配 HihoCoder - 1393
网络流三·二分图多重匹配 HihoCoder - 1393 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int ma ...
- POJ - 3189 Steady Cow Assignment(二分图多重匹配)
题目链接:点击查看 题目大意:给出n只奶牛以及m个牛棚,接下来给出一个n*m的矩阵,给出每一只奶牛对于每个牛棚的喜爱度,按照降序给出,从rank1到rankm,现在问如何分配牛棚能让所有奶牛中最高的r ...
- HDU - 3605 Escape(二分图多重匹配-网络流最大流+思维建边+状态压缩)
题目链接:点击查看 题目大意:到世界末日了,现在人们要逃离去其他的星球,现在给出n个人以及m个星球,再给出每个人可以前往的星球,最后给出每个星球的容量,题目问最多能让多少个人逃离 题目分析:这个题读完 ...
- 【网络流24题】No.7 试题库问题 (最大流,二分图多重匹配)
[题意] 假设一个试题库中有 n 道试题. 每道试题都标明了所属类别. 同一道题可能有多个类别属性.现要从题库中抽取 m 道题组成试卷.并要求试卷包含指定类型的试题. 试设计一个 满足要求的组卷算法. ...
- 网络流三·二分图多重匹配
描述 学校的秋季运动会即将开始,为了决定参赛人员,需要统计分配比赛选手. 已知班级一共有N名学生,编号依次为1..N. 运动会一共有M项不同的比赛,编号为1..M.第i项比赛每个班需要派出m[i]名选 ...
- POJ - 2289 Jamie's Contact Groups(二分图多重匹配)
题目链接:点击查看 题目大意:给出n个联系人,以及m个分组,现在需要将n个联系人分到m个分组中,需要满足让人数最多的组的人数最少,输出这个值 题目分析:因为是让最大值最小,所以肯定是要用二分解决,因为 ...
- [tyvj1935 Poetize3]导弹防御塔 (二分图多重匹配)
传送门 Description Freda控制着N座可以发射导弹的防御塔.每座塔都有足够数量的导弹,但是每座塔每次只能发射一枚.在发射导弹时,导弹需要T1秒才能从防御塔中射出,而在发射导弹后,发射这枚 ...
最新文章
- 微生物生态学相关期刊2022年实时影响因子
- 复制活动记录记录的最简单方法是什么?
- C#编程利器之四:委托与事件(Delegate and event) (上)
- 移动医疗APP(解决方案)下载
- [yum]Another app is currently holding the yum lock
- 2.看板方法---什么是看板方法
- hdu acm 1016
- mysql 分库外置索引,MySQL的分库分表与Innodb的Btree索引
- linux sigar 进程监控,Linux 下使用Sigar 获取CPU 使用率
- 5个免费商用音频素材网站
- [美] 尼古拉斯·卡尔 《浅薄:互联网如何毒化了我们的大脑 》
- “企业上云”计划出炉,三年内河北万家企业要上云!|中机智库
- 西安python培训价格
- 15 | 浮点数和定点数(上):怎么用有限的Bit表示尽可能多的信息?
- 世界五百强企业网站(二)
- 矩阵分析与应用学习笔记1
- 论文略读 | Pattern-revising Enhanced Simple Question Answering over Knowledge Bases
- vue14 动画-自学视频
- js 获取本月第一天和最后一天,上月第一天和最后一天
- net6 winform应用读取配置文件(依赖注入、普通读取)
热门文章
- SpringCloud Config手动刷新及自动刷新
- (原創) Verilog入門書推薦2:數位系統實習 Quartus II (SOC) (Verilog)
- MySQL:浅析 Impossible WHERE noticed after reading const tables
- 无人机成为黑客的新工具,可黑掉部分家用的智能设备
- 值得学习的C/C++开源框架(转)
- [NOI2014]魔法森林
- 译 | 像使用一台主机一样管理集群
- long long _int64使用总结
- lisp 标注螺纹孔_螺纹的表示法和标注
- .set伪指令(mips)