从前一个和谐的班级,有 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 二分图最大权匹配 [模板题]相关推荐

  1. 【算法笔记】二分图最大权匹配 - KM算法(dfs版O(n4) + bfs版O(n3))

    整理的算法模板合集: ACM模板 匈牙利算法又称为 KM 算法,可以在 O(n3)O(n^3)O(n3) 时间内求出二分图的 最大权完美匹配 . 考虑到二分图中两个集合中的点并不总是相同,为了能应用 ...

  2. 二分图最大权匹配问题KM算法讲解 HDU 2255 奔小康赚大钱

    作者:logosG 链接:https://www.cnblogs.com/logosG/p/logos.html (讲解的KM算法,特别厉害!!!) KM算法: 现在我们来考虑另外一个问题:如果每个员 ...

  3. 二分图最大权匹配 KM算法

    KM算法的正确性基于以下定理: 若由二分图中所有满足A[i]+B[i]=w[i][j]的边C(i,j)构成的子图(即相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配 基本概念 1.完备匹配 ...

  4. HDU - 2255 奔小康赚大钱(二分图最大权匹配+KM)

    题目链接:点击查看 题目大意:中文题目,简单来说就是n个人和n个房子最大匹配,需要一一对应并且满足权值和最大 题目分析:二分图的完备匹配,条件完全符合KM算法的局限性,直接套模板即可,后续学习费用流( ...

  5. BZOJ 1937: [Shoi2004]Mst 最小生成树 [二分图最大权匹配]

    传送门 题意: 给一张无向图和一棵生成树,改变一些边的权值使生成树为最小生成树,代价为改变权值和的绝对值,求最小代价 线性规划的形式: $Min\quad \sum\limits_{i=1}^{m} ...

  6. HDU 2255 二分图最佳匹配 模板题

    题目大意: 给定每一个人能支付的房子价值,每个人最多且必须拥有一套房子,问最后分配房子可得到的最大收益 抄了个别人的KM模板,就这样了... 1 #include <cstdio> 2 # ...

  7. uva 11383(二分图最大权匹配)

    题意:一个n*n的矩阵每个格子里有一个正整数w(i,j)你的任务是确定每行一个整数row(i)每列一个整数col(i),对每个格子都有w(i,j)<=row(i)+col(j)所有row(i)和 ...

  8. 【图】二分图最大权匹配

    近代数学选讲的作业,写了五个小时(大部分参考<图论与网络最优化算法>龚劬 编),由于word公式直接粘来会出来乱码所以保存成了图片格式,凑合看吧~~~

  9. 二分图最大匹配及最大权匹配

    二分图最大匹配学习 一.二分图的基本知识 二.二分图最大匹配 什么是二分图最大匹配 怎么求二分图最大匹配 三.二分图最大权匹配 四.例题训练 三.最小点覆盖数 一位大佬的神级解释 本以为有了网络流,就 ...

最新文章

  1. 远程控制软件VNC教程和对内网机器控制的实现
  2. ​Openresty最佳案例 | 第8篇:RBAC介绍、sql和redis模块工具类
  3. 第六回严重鄙视360安全卫士
  4. 浅读设计模式 - 1
  5. java的开源项目哪里找,我想参加开源项目的开发,请问在网上去哪找这样的项目? 纯C语言的(非C++或JAVA)...
  6. 2.4g 无线键鼠对码软件_无线路由器的2.4G和5G同时开速度有影响吗?
  7. 排序算法-08基数排序(python实现)
  8. 【Git】Git 修改刚提交的 commit message
  9. Java技术:Spring Boot 配置文件敏感信息加密
  10. Apollo进阶课程 ⑥ | 高精地图与自动驾驶的关系
  11. stream去重_使用Java Stream API中DistinctBy删除重复数据
  12. 算法导论——排序算法
  13. MongoDB工具介绍
  14. Cocos2d-x建工程时避免copy文件夹和库
  15. iOS UIWebView清除缓存
  16. 简单理解Zookeeper的Leader选举
  17. 成为一名初级游戏策划
  18. wordpress英文主题怎样汉化成中文网站模板
  19. Flink POJO类状态使用注意事项
  20. XP pro下安装Windows XP Tablet PC 2005组件教程

热门文章

  1. Python中常用的高阶函数
  2. 打开ADS提示23111@localhost后提示无法与执照伺服机连线,怎么解决?
  3. java把二维转换为一维_在R语言中什么函数可以将二维数组转换成一维数组
  4. EndDialog和CDialog::OnOK()
  5. sqoop mysql hadoop_使用sqoop将mysql数据导入到hadoop
  6. 织梦php 中英文加手机,织梦dedecms系统中英文网站之中英文搜索结果
  7. 怎么将多个html组合_技巧分享之在HTML元素中添加逼真阴影的教程
  8. kubectl 创建pvc_动态挂载云盘(PVC)
  9. 群晖 内置mysql_群晖DS218+部署mysql
  10. Simulink中DPCM量化和编码仿真