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写法被无情卡掉
/*by SilverN*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#define LL long long
using namespace std;
const LL INF=1LL<<;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void write(LL x){
if(x>)write(x/);
putchar(x%+'');
return;
}
inline LL mini(LL a,LL b){return a<b?a:b;}
inline LL maxi(LL a,LL b){return a>b?a:b;}
int nL,nR,bl,br,m;
int visL[mxn],visR[mxn];
LL exL[mxn],exR[mxn];
int link[mxn];
LL slack[mxn];
int mp[mxn][mxn];
LL ans=;
int a[mxn];
int dtime=;
bool DFS(int u){
visL[u]=dtime;
for(int i=;i<=nR;i++){
if(visR[i]==dtime)continue;
LL d=exL[u]+exR[i]-mp[u][i];
if(!d){
visR[i]=dtime;
if(!link[i] || DFS(link[i])){
link[i]=u;
return ;
}
}
else slack[i]=min(slack[i],d);
}
return ;
}
void KM(){
// memset(link,0,sizeof link);
// memset(exR,0,sizeof exR);
for(int i=;i<=nL;i++){
exL[i]=;
for(int j=;j<=nR;j++){
exL[i]=maxi(exL[i],mp[i][j]);
}
}
for(int i=;i<=nL;i++){
// memset(slack,0x3f,sizeof slack);
for(int j=;j<=nR;j++)slack[j]=INF;
while(){//直到匹配成功为止
dtime++;
// memset(visL,0,sizeof visL);
// memset(visR,0,sizeof visR);
if(DFS(i))break;
LL d=INF;
for(int j=;j<=nR;j++){
if(visR[j]!=dtime)d=mini(d,slack[j]);
}
for(int j=;j<=nL;j++){
if(visL[j]==dtime)exL[j]-=d;
if(visR[j]==dtime)exR[j]+=d;
else slack[j]-=d;
}
}
}
ans=;
nL=bl;nR=br;
for(int i=;i<=nR;i++){
if(mp[link[i]][i]){
a[link[i]]=i;
ans+=mp[link[i]][i];
}
}
printf("%lld\n",ans);
for(int i=;i<=nL;i++){
write(a[i]);
putchar(' ');
}
printf("\n");
return;
}
int main(){
int i,j;
nL=read();
nR=read();
bl=nL;br=nR;
nL=max(nL,nR);
nR=nL;
m=read();
int u,v,w;
for(i=;i<=m;i++){
u=read();v=read();w=read();
mp[u][v]=w;
}
KM();
return ;
}
DFS TLE
于是在status里抄了个BFS的写法。
/*by SilverN*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void write(LL x){
if(x>)write(x/);
putchar(x%+'');
return;
}
inline int mini(int a,int b){return a<b?a:b;}
inline int maxi(int a,int b){return a>b?a:b;}
int nL,nR,bl,br,m;
int visL[mxn],visR[mxn];
int exL[mxn],exR[mxn];
int link[mxn],pre[mxn],lx[mxn];
int slack[mxn];
int mp[mxn][mxn];
//
LL ans=;
int a[mxn];
int dtime=;
int q[mxn<<],hd,tl;
void Aug(int rt){
if(!rt)return;
link[rt]=pre[rt];
Aug(lx[pre[rt]]);
lx[pre[rt]]=rt;
return;
}
void BFS(int S){
int i,j,tmp;++dtime;
memset(slack,0x3f,sizeof slack);
hd=tl=;q[tl]=S;
while(){
while(hd<=tl){
int u=q[hd];++hd;
visL[u]=dtime;
for(int i=;i<=nR;i++){
if(visR[i]^dtime){
tmp=exL[u]+exR[i]-mp[u][i];
if(!tmp){
visR[i]=dtime;pre[i]=u;
if(!link[i]){
Aug(i);
return;
}
q[++tl]=link[i];
//
}
else if(tmp<slack[i])slack[i]=tmp,pre[i]=u;
}
}
}
tmp=INF;
for(i=;i<=nR;i++)if(visR[i]^dtime)tmp=mini(tmp,slack[i]);
for(i=;i<=nL;i++){
if(visL[i]==dtime)exL[i]-=tmp;
if(visR[i]==dtime)exR[i]+=tmp;
else slack[i]-=tmp;
}
for(i=;i<=nR;i++){
if(visR[i]^dtime && !slack[i]){
visR[i]=dtime;
if(!link[i]){
// link[i]=pre[i];
Aug(i);
return;
}
q[++tl]=link[i];
}
}
}
return;
}
void KM(){
for(int i=;i<=nL;i++){
exL[i]=;
for(int j=;j<=nR;j++)
exL[i]=max(exL[i],mp[i][j]);
}
for(int i=;i<=nL;i++) BFS(i);
ans=;
nL=bl;nR=br;
for(int i=;i<=nR;i++){
if(mp[link[i]][i]){
a[link[i]]=i;
ans+=mp[link[i]][i];
}
}
printf("%lld\n",ans);
for(int i=;i<=nL;i++){
write(a[i]);
putchar(' ');
}
printf("\n");
return;
}
int main(){
int i,j;
nL=read();
nR=read();
bl=nL;br=nR;
nL=max(nL,nR);
nR=nL;
m=read();
int u,v,w;
for(i=;i<=m;i++){
u=read();v=read();w=read();
mp[u][v]=w;
}
KM();
return ;
}
UOJ#80 二分图最大权匹配 [模板题]的更多相关文章
- UOJ#80. 二分图最大权匹配 模板
#80. 二分图最大权匹配 描述 提交 自定义测试 从前一个和谐的班级,有 nlnl 个是男生,有 nrnr 个是女生.编号分别为 1,…,nl1,…,nl 和 1,…,nr1,…,nr. 有若干个这 ...
- uoj#80 二分图最大权匹配
题意:给定二分图,有边权,求最大边权匹配.边权非负. 解:KM算法求解最大权完备匹配. 完备匹配就是点数少的那一边每个点都有匹配. 为了让完备匹配与最大权匹配等价,我们添加若干条0边使之成为完全二分图 ...
- [SDOI2006] 仓库管理员的烦恼 - 二分图最大权匹配
最小化代价,即最大化"本土"货物的数量 于是就是个二分图最大权匹配裸题 #include <bits/stdc++.h> using namespace std; #d ...
- @noi.ac - 507@ 二分图最大权匹配
目录 @description@ @solution@ @accepted code@ @details@ @description@ 有一天你学了一个能解决二分图最大权匹配的算法,你决定将这个算法应 ...
- HDU2255 奔小康赚大钱 —— 二分图最大权匹配 KM算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) ...
- [ACM] HDU 2255 奔小康赚大钱 (二分图最大权匹配,KM算法)
奔小康赚大钱 Problem Description 传说在遥远的地方有一个很富裕的村落,有一天,村长决定进行制度改革:又一次分配房子. 这但是一件大事,关系到人民的住房问题啊. 村里共同拥有n间房间 ...
- [SDOI2017] 新生舞会 - 二分图最大权匹配,分数规划,二分答案
有一个二分图,每个部都有 \(n\) 个点,每条边有两个参数 \(a_e, b_e\),求一种匹配,使得 \(\sum a_i / \sum b_i\) 最大 Solution 显然的分数规划,考虑二 ...
- [hdu1533]二分图最大权匹配 || 最小费用最大流
题意:给一个n*m的地图,'m'表示人,'H'表示房子,求所有人都回到房子所走的距离之和的最小值(距离为曼哈顿距离). 思路:比较明显的二分图最大权匹配模型,将每个人向房子连一条边,边权为曼哈顿距离的 ...
- POJ2195 Going Home[费用流|二分图最大权匹配]
Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22088 Accepted: 11155 Desc ...
随机推荐
- 实用脚本 2 -- Linux下定时执行脚本
今天学习Linux下定时执行脚本,看到一篇讲解比较好的文章,特此拿来分享. 原文链接:http://www.blogjava.net/decode360/archive/2009/09/18/2877 ...
- 掘金 Android 文章精选合集
掘金 Android 文章精选合集 掘金官方 关注 2017.07.10 16:42* 字数 175276 阅读 50053评论 13喜欢 669 用两张图告诉你,为什么你的 App 会卡顿? - A ...
- 项目总结(一)->项目的七宗罪
大半夜来这一份总结,心中夹杂着各种各样的心情,酸甜苦辣都有,今天为止,整个项目终于完结了,对于这样一个本可以正而八经吃吃薯片,看看毛片就可以完成项目,最后演变成一个一月之内连续加班105个小时的项目, ...
- 谷歌js编码规范解析
http://alloyteam.github.io/JX/doc/specification/google-javascript.xm 阅读了谷歌js编码规范,我发现了很多,js的里面很多要注意的问 ...
- 数据库sql命令
本文为转载,原文地址:http://www.cnblogs.com/cangqiongbingchen/p/4530333.html 1.说明:创建数据库CREATE DATABASE databas ...
- Uva 12627 Erratic Expansion(递归)
这道题大体意思是利用一种递归规则生成不同的气球,问在某两行之间有多少个红气球. 我拿到这个题,一开始想的是递归求解,但在如何递归求解的思路上我的方法是错误的.在研读了例题上给出的提示后豁然开朗(顺便吐 ...
- DPDK vhost库
原创翻译,转载请注明出处. vhost库实现了一个用户空间的virtio net server,允许用户直接处理virtio ring队列.换句话说,它让用户可以从VM virtio网络设备读取或写入 ...
- C# Lambda表达式使用累加器例子
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Lamb ...
- 201621044079《Java程序设计》第二周学习总结
Week02-Java基本语法与类库 1.本周学习总结 记录本周学习中的重点 尝试使用 原则:少而精,自己写.即使不超过5行也可,但请一定不要简单的复制粘贴 1.学习了Java的数据类型 int ch ...
- Maven中如何将源码之外的文件打包及添加本地jar
<build> <resources> <resource> <directory>src/main/resources</directory&g ...