UOJ#80 二分图最大权匹配 [模板题]
从前一个和谐的班级,有 nlnl 个是男生,有 nrnr 个是女生。编号分别为 1,…,nl1,…,nl 和 1,…,nr1,…,nr。
有若干个这样的条件:第 vv 个男生和第 uu 个女生愿意结为配偶,且结为配偶后幸福程度为 ww。
请问这个班级里幸福程度之和最大是多少?
输入格式
第一行三个正整数,nl,nr,mnl,nr,m。
接下来 mm 行,每行三个整数 v,u,wv,u,w 表示第 vv 个男生和第 uu 个女生愿意结为配偶,且幸福程度为 ww。保证 1≤v≤nl1≤v≤nl,1≤u≤nr1≤u≤nr,保证同一对 v,uv,u 不会出现两次。
输出格式
第一行一个整数,表示幸福程度之和的最大值。
接下来一行 nlnl 个整数,描述一组最优方案。第 vv 个整数表示 vv 号男生的配偶的编号。如果 vv 号男生没配偶请输出 00。
样例一
input
2 2 3 1 1 100 1 2 1 2 1 1
output
100 1 0
限制与约定
1≤nl,nr≤4001≤nl,nr≤400,1≤m≤1600001≤m≤160000,1≤w≤1091≤w≤109。
时间限制:1s1s
空间限制:256MB
二分图最大权匹配模板题 KM算法
KM算法略神奇的样子……
http://www.cnblogs.com/wenruo/p/5264235.html
↑感觉这里讲得挺清晰
KM算法求的是最大权完备匹配,为了解决两边点数不同的情况,需要虚拟一些点使得两边点数相等
↑但是这种DFS写法被无情卡掉
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 #define LL long long 9 using namespace std; 10 const LL INF=1LL<<62; 11 const int mxn=411; 12 int read(){ 13 int x=0,f=1;char ch=getchar(); 14 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 15 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 void write(LL x){ 19 if(x>9)write(x/10); 20 putchar(x%10+'0'); 21 return; 22 } 23 inline LL mini(LL a,LL b){return a<b?a:b;} 24 inline LL maxi(LL a,LL b){return a>b?a:b;} 25 int nL,nR,bl,br,m; 26 int visL[mxn],visR[mxn]; 27 LL exL[mxn],exR[mxn]; 28 int link[mxn]; 29 LL slack[mxn]; 30 int mp[mxn][mxn]; 31 LL ans=0; 32 int a[mxn]; 33 int dtime=0; 34 bool DFS(int u){ 35 visL[u]=dtime; 36 for(int i=1;i<=nR;i++){ 37 if(visR[i]==dtime)continue; 38 LL d=exL[u]+exR[i]-mp[u][i]; 39 if(!d){ 40 visR[i]=dtime; 41 if(!link[i] || DFS(link[i])){ 42 link[i]=u; 43 return 1; 44 } 45 } 46 else slack[i]=min(slack[i],d); 47 } 48 return 0; 49 } 50 void KM(){ 51 // memset(link,0,sizeof link); 52 // memset(exR,0,sizeof exR); 53 for(int i=1;i<=nL;i++){ 54 exL[i]=0; 55 for(int j=1;j<=nR;j++){ 56 exL[i]=maxi(exL[i],mp[i][j]); 57 } 58 } 59 for(int i=1;i<=nL;i++){ 60 // memset(slack,0x3f,sizeof slack); 61 for(int j=1;j<=nR;j++)slack[j]=INF; 62 while(1){//直到匹配成功为止 63 dtime++; 64 // memset(visL,0,sizeof visL); 65 // memset(visR,0,sizeof visR); 66 if(DFS(i))break; 67 LL d=INF; 68 for(int j=1;j<=nR;j++){ 69 if(visR[j]!=dtime)d=mini(d,slack[j]); 70 } 71 for(int j=1;j<=nL;j++){ 72 if(visL[j]==dtime)exL[j]-=d; 73 if(visR[j]==dtime)exR[j]+=d; 74 else slack[j]-=d; 75 } 76 } 77 } 78 ans=0; 79 nL=bl;nR=br; 80 for(int i=1;i<=nR;i++){ 81 if(mp[link[i]][i]){ 82 a[link[i]]=i; 83 ans+=mp[link[i]][i]; 84 } 85 } 86 printf("%lld\n",ans); 87 for(int i=1;i<=nL;i++){ 88 write(a[i]); 89 putchar(' '); 90 } 91 printf("\n"); 92 return; 93 } 94 int main(){ 95 int i,j; 96 nL=read(); 97 nR=read(); 98 bl=nL;br=nR; 99 nL=max(nL,nR); 100 nR=nL; 101 m=read(); 102 int u,v,w; 103 for(i=1;i<=m;i++){ 104 u=read();v=read();w=read(); 105 mp[u][v]=w; 106 } 107 KM(); 108 return 0; 109 }
DFS TLE
于是在status里抄了个BFS的写法。
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 #define LL long long 9 using namespace std; 10 const int INF=0x3f3f3f3f; 11 const int mxn=411; 12 int read(){ 13 int x=0,f=1;char ch=getchar(); 14 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 15 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 void write(LL x){ 19 if(x>9)write(x/10); 20 putchar(x%10+'0'); 21 return; 22 } 23 inline int mini(int a,int b){return a<b?a:b;} 24 inline int maxi(int a,int b){return a>b?a:b;} 25 int nL,nR,bl,br,m; 26 int visL[mxn],visR[mxn]; 27 int exL[mxn],exR[mxn]; 28 int link[mxn],pre[mxn],lx[mxn]; 29 int slack[mxn]; 30 int mp[mxn][mxn]; 31 // 32 LL ans=0; 33 int a[mxn]; 34 int dtime=0; 35 int q[mxn<<1],hd,tl; 36 void Aug(int rt){ 37 if(!rt)return; 38 link[rt]=pre[rt]; 39 Aug(lx[pre[rt]]); 40 lx[pre[rt]]=rt; 41 return; 42 } 43 void BFS(int S){ 44 int i,j,tmp;++dtime; 45 memset(slack,0x3f,sizeof slack); 46 hd=tl=1;q[tl]=S; 47 while(1){ 48 while(hd<=tl){ 49 int u=q[hd];++hd; 50 visL[u]=dtime; 51 for(int i=1;i<=nR;i++){ 52 if(visR[i]^dtime){ 53 tmp=exL[u]+exR[i]-mp[u][i]; 54 if(!tmp){ 55 visR[i]=dtime;pre[i]=u; 56 if(!link[i]){ 57 Aug(i); 58 return; 59 } 60 q[++tl]=link[i]; 61 // 62 } 63 else if(tmp<slack[i])slack[i]=tmp,pre[i]=u; 64 } 65 } 66 } 67 tmp=INF; 68 for(i=1;i<=nR;i++)if(visR[i]^dtime)tmp=mini(tmp,slack[i]); 69 for(i=1;i<=nL;i++){ 70 if(visL[i]==dtime)exL[i]-=tmp; 71 if(visR[i]==dtime)exR[i]+=tmp; 72 else slack[i]-=tmp; 73 } 74 for(i=1;i<=nR;i++){ 75 if(visR[i]^dtime && !slack[i]){ 76 visR[i]=dtime; 77 if(!link[i]){ 78 // link[i]=pre[i]; 79 Aug(i); 80 return; 81 } 82 q[++tl]=link[i]; 83 } 84 } 85 } 86 return; 87 } 88 void KM(){ 89 for(int i=1;i<=nL;i++){ 90 exL[i]=0; 91 for(int j=1;j<=nR;j++) 92 exL[i]=max(exL[i],mp[i][j]); 93 } 94 for(int i=1;i<=nL;i++) BFS(i); 95 ans=0; 96 nL=bl;nR=br; 97 for(int i=1;i<=nR;i++){ 98 if(mp[link[i]][i]){ 99 a[link[i]]=i; 100 ans+=mp[link[i]][i]; 101 } 102 } 103 printf("%lld\n",ans); 104 for(int i=1;i<=nL;i++){ 105 write(a[i]); 106 putchar(' '); 107 } 108 printf("\n"); 109 return; 110 } 111 int main(){ 112 int i,j; 113 nL=read(); 114 nR=read(); 115 bl=nL;br=nR; 116 nL=max(nL,nR); 117 nR=nL; 118 m=read(); 119 int u,v,w; 120 for(i=1;i<=m;i++){ 121 u=read();v=read();w=read(); 122 mp[u][v]=w; 123 } 124 KM(); 125 return 0; 126 }
转载于:https://www.cnblogs.com/SilverNebula/p/6710604.html
UOJ#80 二分图最大权匹配 [模板题]相关推荐
- 【算法笔记】二分图最大权匹配 - KM算法(dfs版O(n4) + bfs版O(n3))
整理的算法模板合集: ACM模板 匈牙利算法又称为 KM 算法,可以在 O(n3)O(n^3)O(n3) 时间内求出二分图的 最大权完美匹配 . 考虑到二分图中两个集合中的点并不总是相同,为了能应用 ...
- 二分图最大权匹配问题KM算法讲解 HDU 2255 奔小康赚大钱
作者:logosG 链接:https://www.cnblogs.com/logosG/p/logos.html (讲解的KM算法,特别厉害!!!) KM算法: 现在我们来考虑另外一个问题:如果每个员 ...
- 二分图最大权匹配 KM算法
KM算法的正确性基于以下定理: 若由二分图中所有满足A[i]+B[i]=w[i][j]的边C(i,j)构成的子图(即相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配 基本概念 1.完备匹配 ...
- HDU - 2255 奔小康赚大钱(二分图最大权匹配+KM)
题目链接:点击查看 题目大意:中文题目,简单来说就是n个人和n个房子最大匹配,需要一一对应并且满足权值和最大 题目分析:二分图的完备匹配,条件完全符合KM算法的局限性,直接套模板即可,后续学习费用流( ...
- BZOJ 1937: [Shoi2004]Mst 最小生成树 [二分图最大权匹配]
传送门 题意: 给一张无向图和一棵生成树,改变一些边的权值使生成树为最小生成树,代价为改变权值和的绝对值,求最小代价 线性规划的形式: $Min\quad \sum\limits_{i=1}^{m} ...
- HDU 2255 二分图最佳匹配 模板题
题目大意: 给定每一个人能支付的房子价值,每个人最多且必须拥有一套房子,问最后分配房子可得到的最大收益 抄了个别人的KM模板,就这样了... 1 #include <cstdio> 2 # ...
- uva 11383(二分图最大权匹配)
题意:一个n*n的矩阵每个格子里有一个正整数w(i,j)你的任务是确定每行一个整数row(i)每列一个整数col(i),对每个格子都有w(i,j)<=row(i)+col(j)所有row(i)和 ...
- 【图】二分图最大权匹配
近代数学选讲的作业,写了五个小时(大部分参考<图论与网络最优化算法>龚劬 编),由于word公式直接粘来会出来乱码所以保存成了图片格式,凑合看吧~~~
- 二分图最大匹配及最大权匹配
二分图最大匹配学习 一.二分图的基本知识 二.二分图最大匹配 什么是二分图最大匹配 怎么求二分图最大匹配 三.二分图最大权匹配 四.例题训练 三.最小点覆盖数 一位大佬的神级解释 本以为有了网络流,就 ...
最新文章
- 远程控制软件VNC教程和对内网机器控制的实现
- ​Openresty最佳案例 | 第8篇:RBAC介绍、sql和redis模块工具类
- 第六回严重鄙视360安全卫士
- 浅读设计模式 - 1
- java的开源项目哪里找,我想参加开源项目的开发,请问在网上去哪找这样的项目? 纯C语言的(非C++或JAVA)...
- 2.4g 无线键鼠对码软件_无线路由器的2.4G和5G同时开速度有影响吗?
- 排序算法-08基数排序(python实现)
- 【Git】Git 修改刚提交的 commit message
- Java技术:Spring Boot 配置文件敏感信息加密
- Apollo进阶课程 ⑥ | 高精地图与自动驾驶的关系
- stream去重_使用Java Stream API中DistinctBy删除重复数据
- 算法导论——排序算法
- MongoDB工具介绍
- Cocos2d-x建工程时避免copy文件夹和库
- iOS UIWebView清除缓存
- 简单理解Zookeeper的Leader选举
- 成为一名初级游戏策划
- wordpress英文主题怎样汉化成中文网站模板
- Flink POJO类状态使用注意事项
- XP pro下安装Windows XP Tablet PC 2005组件教程
热门文章
- Python中常用的高阶函数
- 打开ADS提示23111@localhost后提示无法与执照伺服机连线,怎么解决?
- java把二维转换为一维_在R语言中什么函数可以将二维数组转换成一维数组
- EndDialog和CDialog::OnOK()
- sqoop mysql hadoop_使用sqoop将mysql数据导入到hadoop
- 织梦php 中英文加手机,织梦dedecms系统中英文网站之中英文搜索结果
- 怎么将多个html组合_技巧分享之在HTML元素中添加逼真阴影的教程
- kubectl 创建pvc_动态挂载云盘(PVC)
- 群晖 内置mysql_群晖DS218+部署mysql
- Simulink中DPCM量化和编码仿真