草,学了一下午假板子,sb博客害人

题目大意:

一个教室有\(n\)个男生和\(m\)个女生,某些男女之间愿意早恋(雾),其早恋好感度为\(w_i\),问怎样让男女配对使得班里好感度之和最大

\(n\le 400\)

二分图最优匹配模型,KM算法板子题

二分图中我们介绍了一些定义,包括最优匹配、完美匹配、顶标、相等子图

相等子图的完美匹配就是二分图的最优匹配

我们考虑先给每个点赋顶标,或者说对于好感度的期望值

首先每个男生的期望是她愿意早恋对象的好感度的最大值,女生是\(0\)(即每个男生都想要最喜欢的人,女生都很佛)

这样必定满足\(a_u+b_v\ge val(u,v)\)

然后试图在这个的相等子图中寻找完美匹配

不过大概率找不到

找不到怎么办呢?一般是出现了两个男生想要一个女生的情况,那么我们只能给某一个男生安排另外的女生,所以我们要降低已经匹配过男生的期望

当然为了不漏掉任何一个女生,我们不能降低的太多,应该降低到刚好刚才没被人选过的女生可以入选

也就是说我们对于每个刚才挑过人的男生,应该降低\(d=min\{a_u+b_v-val(u,v)\}\)其中\(vis_{boy}[u]=1,vis_{girl}[v]=0\)

但是男生们期望降低了,刚才匹配过的女生不能不要啊\(qwq\),所以应该将刚才每个匹配过的女生期望增加\(d\)保证刚才被匹配过的女生不会被丢出相等子图

这样会保证参与过匹配的边不会被踢出匹配,同时保证有新的右部节点参与匹配

但是\(n\ne m\)的情况怎么办啊(雾)

那为了匹配顺利,我们只能添加好感度为\(0\)的假人了……

具体实现一些细节在代码里面:

\(dfs\)版本:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
namespace red{
#define int long long
#define eps (1e-8)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=410,inf=0x3f3f3f3f;
int n,m,k;
int bl,br;
int head[N],cnt;
int love[N][N];
int g[N];
int f[N],ex_girl[N],ex_boy[N];
int slack[N];
bool vis_boy[N],vis_girl[N];
inline bool find(int boy)//稍微魔改过的匈牙利
{
vis_boy[boy]=1;
for(int girl=1;girl<=m;++girl)
{
if(vis_girl[girl]) continue;
int gap=ex_boy[boy]+ex_girl[girl]-love[boy][girl];
if(gap==0)//如果是相等子图,直接更新
{
vis_girl[girl]=1;
if(!f[girl]||find(f[girl]))
{
f[girl]=boy;
g[boy]=girl;
return 1;
}
}
else//不是的话记录一下最少改变多少期望
{
slack[girl]=min(slack[girl],gap);
}
}
return 0;
}
inline void km()
{
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
ex_boy[i]=max(ex_boy[i],love[i][j]);//男生初始期望是所有好感度最大值
}
}
for(int i=1;i<=n;++i)
{
memset(slack,inf,sizeof(slack));
memset(vis_boy,0,sizeof(vis_boy));
memset(vis_girl,0,sizeof(vis_girl));
if(find(i)) continue;//如果直接匹配成功就可以跳了
while("haku")//失败了,扩大相等子图范围
{
int d=inf,t;
for(int j=1;j<=n;++j)
if(!vis_girl[j]) d=min(d,slack[j]);//找到女生没被匹配过里面需要降低的最小值
for(int j=1;j<=n;++j)
{
if(vis_boy[j]) ex_boy[j]-=d;//匹配过的男生降低d
if(vis_girl[j]) ex_girl[j]+=d;//匹配过的女生提高d
else//没被匹配过的女生
{
slack[j]-=d;
if(!slack[j]) t=j;//如果男生全部削减完d之后可以进入相等子图,做个标记
}
}
if(!f[t]) break;//如果进入的女生没有配对的男生,那么说明我们可以找到新的一对,变成完美匹配
vis_girl[t]=1,vis_boy[f[t]]=1;//否则继续改变期望
t=f[t];
for(int j=1;j<=n;++j)
slack[j]=min(slack[j],ex_boy[t]+ex_girl[j]-love[t][j]);
}//注意不要在里面多次匈牙利,复杂度会炸
memset(vis_boy,0,sizeof(vis_boy));
memset(vis_girl,0,sizeof(vis_girl));
find(i);
}
int ret=0;
for(int i=1;i<=bl;++i)
{
ret+=love[i][g[i]];
}
printf("%lld\n",ret);
for(int i=1;i<=bl;++i) printf("%lld ",love[i][g[i]]?g[i]:0ll);
puts("");
}
inline void main()
{
n=read(),m=read(),k=read();
bl=n,br=m;
n=max(n,m),m=n;//假人代打
for(int x,y,w,i=1;i<=k;++i)
{
x=read(),y=read(),w=read();
love[x][y]=w;
}
km();
}
}
signed main()
{
red::main();
return 0;
}

\(bfs\)版本鸽子了,以后有空再补吧

UOJ80 二分图最大权匹配的更多相关文章

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

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

  2. Hdu2255 奔小康赚大钱(二分图最大权匹配KM算法)

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

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

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

  4. POJ2195 Going Home (最小费最大流||二分图最大权匹配) 2017-02-12 12:14 131人阅读 评论(0) 收藏

    Going Home Description On a grid map there are n little men and n houses. In each unit time, every l ...

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

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

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

    前言 这东西虽然我早就学过了,但是最近才发现我以前学的是假的,心中感慨万千(雾),故作此篇. 简介 带权二分图:每条边都有权值的二分图 最大权匹配:使所选边权和最大的匹配 KM算法,全称Kuhn-Mu ...

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

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

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

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

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

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

随机推荐

  1. setPriority()优先级

    1 . 优先级表示重要程度或者紧急程度.但是能不能抢到资源也是不一定.2 . 分配优先级:反映线程的重要或紧急程度线程的优先级用1-10 表示,1的优先级最低,10的优先级最高,默认值是5 packa ...

  2. Java字符类型(详解)

    [1]Java中使用单引号来表示字符常量,字符型在内存中占2个字节. char 类型用来表示在Unicode编码表中的字符.Unicode编码被设计用来处理各种语言的文字,它占2个字节,可允许有655 ...

  3. CSS opacity设置不透明度

    1.opacity设置不透明度 opacity会将含有这个属性的子类都变成具有opacity属性,可以改变元素.元素内容.字标签的不透明度.而rgba只会改变设置的那个背景颜色的透明度效果 <! ...

  4. Weblogic CVE-2020-2551漏洞复现&CS实战利用

    Weblogic CVE-2020-2551漏洞复现 Weblogic IIOP 反序列化 漏洞原理 https://www.anquanke.com/post/id/199227#h3-7 http ...

  5. Docker学习第一天(Docker入门&&Docker镜像管理)

    简介 今天小区的超市买零食老板给我说再过几天可能就卖完了我有点诧异,老板又说厂家不生产了emmm 今天总算开始docker了! 1.Docker? 1.什么是Docker Docker 是一个开源的应 ...

  6. Guitar Pro的10个非常实用的技巧(下)

    Guitar Pro 7具有许多功能和编辑选项,只需点击几下即可随时创建与编辑我们的乐谱,.以下就为大家介绍10个Guitar Pro中实用的技巧,可以大大的节省我们的时间. 上次在<Guita ...

  7. 如何在FL Studio中使用自动剪辑(上)

    一.什么是FL Studio Automation FL Studio automation可以通过许多不同的方法实现.一种方法是使用自动化剪辑(automation clip).自动化剪辑(或包络线 ...

  8. Camtasia Studio,一款好用到爆炸的视频录制软件

    目前网络中有很多视频录制软件,各有特色,经过亲测今天小编为大家推荐一款比较好的视频录制软件就是Camtasia Studio软件,Camtasia支持视频的高清录制以及视频的导入导出,而且最支持导出的 ...

  9. Yali 2019-8-15 test solution

    T1. 送货 Description 物流公司要用m辆车派送n件货物.货物都包装成长方体,第i件的高度为hi,重量为wi.因为车很小,一辆车上的货物必须垒成一摞.又因为一些不可告人的原因,一辆车上货物 ...

  10. CentOS 防火墙常用命令

    1.查看防火墙状态: firewall-cmd --state 2.启动防火墙 systemctl start firewalld 3.关闭防火墙 systemctl stop firewalld 4 ...