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

  1. UOJ#80. 二分图最大权匹配 模板

    #80. 二分图最大权匹配 描述 提交 自定义测试 从前一个和谐的班级,有 nlnl 个是男生,有 nrnr 个是女生.编号分别为 1,…,nl1,…,nl 和 1,…,nr1,…,nr. 有若干个这 ...

  2. uoj#80 二分图最大权匹配

    题意:给定二分图,有边权,求最大边权匹配.边权非负. 解:KM算法求解最大权完备匹配. 完备匹配就是点数少的那一边每个点都有匹配. 为了让完备匹配与最大权匹配等价,我们添加若干条0边使之成为完全二分图 ...

  3. [SDOI2006] 仓库管理员的烦恼 - 二分图最大权匹配

    最小化代价,即最大化"本土"货物的数量 于是就是个二分图最大权匹配裸题 #include <bits/stdc++.h> using namespace std; #d ...

  4. @noi.ac - 507@ 二分图最大权匹配

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 有一天你学了一个能解决二分图最大权匹配的算法,你决定将这个算法应 ...

  5. HDU2255 奔小康赚大钱 —— 二分图最大权匹配 KM算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    ...

  6. [ACM] HDU 2255 奔小康赚大钱 (二分图最大权匹配,KM算法)

    奔小康赚大钱 Problem Description 传说在遥远的地方有一个很富裕的村落,有一天,村长决定进行制度改革:又一次分配房子. 这但是一件大事,关系到人民的住房问题啊. 村里共同拥有n间房间 ...

  7. [SDOI2017] 新生舞会 - 二分图最大权匹配,分数规划,二分答案

    有一个二分图,每个部都有 \(n\) 个点,每条边有两个参数 \(a_e, b_e\),求一种匹配,使得 \(\sum a_i / \sum b_i\) 最大 Solution 显然的分数规划,考虑二 ...

  8. [hdu1533]二分图最大权匹配 || 最小费用最大流

    题意:给一个n*m的地图,'m'表示人,'H'表示房子,求所有人都回到房子所走的距离之和的最小值(距离为曼哈顿距离). 思路:比较明显的二分图最大权匹配模型,将每个人向房子连一条边,边权为曼哈顿距离的 ...

  9. POJ2195 Going Home[费用流|二分图最大权匹配]

    Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22088   Accepted: 11155 Desc ...

随机推荐

  1. Linux - 信息收集

    1. #!,代表加载器(解释器)的路径,如: #!/bin/bash echo "Hello Boy!" 上面的意思是说,把下面的字符(#!/bin/bash以下的所有字符)统统传 ...

  2. LinqToExcel使用简介一

             最近才看到原来也可以用Linq来访问Excel,功能还挺强大的.要使用这个功能,首先得下载一个LinqToExcel的相关文件,然后就可以调用相关的方法.         使用前面介 ...

  3. leetcode笔记--1 two-sum

    my answer: ​​​​出现的问题:倒数第二行and i !=s这种情况没有考虑进去,以后要思考全面些

  4. 【Python】Python内置函数dir详解

    1.命令介绍 最近学习并使用了一个python的内置函数dir,首先help一下: 复制代码代码如下: >>> help(dir)Help on built-in function ...

  5. C语言分支/顺序作业总结

    总结 1.1 基本要求(1分) 按时交 - 有分 未交 - 0分 迟交一周以上 - 倒扣本次作业分数 抄袭 - 0分 博客作业格式不规范,没有用Markdown语法 -扣分 泛泛而谈(最多七分) 1. ...

  6. lintcode-104-合并k个排序链表

    104-合并k个排序链表 合并k个排序链表,并且返回合并后的排序链表.尝试分析和描述其复杂度. 样例 给出3个排序链表[2->4->null,null,-1->null],返回 -1 ...

  7. .Net MVC中使用css 和js

    @section script { <script language="javascript"> </script> }

  8. Java面试题(上)

    2013年年底的时候,我看到了网上流传的一个叫做<Java面试题大全>的东西,认真的阅读了以后发现里面的很多题目是重复且没有价值的题目,还有不少的参考答案也是错误的,于是我花了半个月时间对 ...

  9. coredump分析

    首先通过命令 gdb freeswitch core.60954进入gdb. 这里freeswitch 是产生coredump的可执行应用,core.60954是应用产生的coredump文件. 然后 ...

  10. linux下搜索find命令拾遗

    强制删除项目下面的所有.svn文件目录,find . -name ‘.svn’ -exec rm -rf {} \; empty显示所有的空白文件,并显示详细:find . -empty size显示 ...