当前位置:网站首页>二分图最大权匹配(搭个板子,粘俩题)
二分图最大权匹配(搭个板子,粘俩题)
2022-06-21 19:39:00 【fighting_yifeng】
先讲二分图最大权匹配做了什么:
先说一说人尽皆知csl匈牙利最大匹配做的事是二分图两边点的最大匹配,但如果边权有值咋整呢,这就用到了二分图最大权匹配,让你可以匹配过后获得最大的权值。
沾板子(kuangbin好菜牛逼)
int g[maxn][maxn], linker[maxn], lx[maxn], ly[maxn];
int slack[maxn], nx, ny, t, n, m;
bool visx[maxn], visy[maxn];
bool dfs(int x)
{
visx[x] = 1;
for(int y = 0; y < ny; y++){
if(visy[y]) continue;
int tmp = lx[x] + ly[y] - g[x][y];
if(tmp == 0){
visy[y] = 1;
if(linker[y] == -1 || dfs(linker[y])){
linker[y] = x;
return 1;
}
}
else if(slack[y] > tmp) slack[y] = tmp;
}
return false;
}
int KM()
{
memset(linker, -1, sizeof(linker));
memset(ly, 0, sizeof(ly));
for(int i = 0; i < nx; i++)
{
lx[i] = -INF;
for(int j = 0; j < ny; j++)
if(g[i][j] > lx[i]) lx[i] = g[i][j];
}
for(int x = 0; x < nx; x++){
for(int i = 0; i < ny; i++)
slack[i] = INF;
while(true)
{
memset(visx, false, sizeof(visx));
memset(visy, false, sizeof(visy));
if(dfs(x)) break;
int d = INF;
for(int i = 0; i < ny; i++)
if(!visy[i] && d > slack[i])
d = slack[i];
for(int i = 0; i < nx; i++)
if(visx[i]) lx[i] -= d;
for(int i = 0; i < ny; i++)
if(visy[i]) ly[i] += d;
else slack[i] -= d;
}
}
int res = 0;
for(int i = 0; i < ny; i++)
if(linker[i] != -1)
res += g[linker[i]][i];
return res;
}
粘俩题:
A.最大权匹配
P - 奔小康赚大钱 HDU - 2255
题意:卖房子,每套房子每个人给不同的钱,全卖出去赚最多的钱。
#include <iostream>
#include <cstdio>
#include <stack>
#include <cmath>
#include <set>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
const int INF = 0x3f3f3f3f;
const int maxn = 510;
int g[maxn][maxn], linker[maxn], lx[maxn], ly[maxn];
int slack[maxn], nx, ny;
bool visx[maxn], visy[maxn];
bool dfs(int x)
{
visx[x] = 1;
for(int y = 0; y < ny; y++){
if(visy[y]) continue;
int tmp = lx[x] + ly[y] - g[x][y];
if(tmp == 0){
visy[y] = 1;
if(linker[y] == -1 || dfs(linker[y])){
linker[y] = x;
return 1;
}
}
else if(slack[y] > tmp) slack[y] = tmp;
}
return false;
}
int KM()
{
memset(linker, -1, sizeof(linker));
memset(ly, 0, sizeof(ly));
for(int i = 0; i < nx; i++)
{
lx[i] = -INF;
for(int j = 0; j < ny; j++)
if(g[i][j] > lx[i]) lx[i] = g[i][j];
}
for(int x = 0; x < nx; x++){
for(int i = 0; i < ny; i++)
slack[i] = INF;
while(true)
{
memset(visx, false, sizeof(visx));
memset(visy, false, sizeof(visy));
if(dfs(x)) break;
int d = INF;
for(int i = 0; i < ny; i++)
if(!visy[i] && d > slack[i])
d = slack[i];
for(int i = 0; i < nx; i++)
if(visx[i]) lx[i] -= d;
for(int i = 0; i < ny; i++)
if(visy[i]) ly[i] += d;
else slack[i] -= d;
}
}
int res = 0;
for(int i = 0; i < ny; i++)
if(linker[i] != -1)
res += g[linker[i]][i];
return res;
}
int main()
{
int n;
while(~scanf("%d", &n))
{
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
scanf("%d", &g[i][j]);
nx = ny = n;
printf("%d\n", KM());
}
return 0;
}
B最小权最大匹配
Q - Tour HDU - 3488
题意:n条道路经过n个城市回到原点,然后问最小行程距离。
#include <iostream>
#include <cstdio>
#include <stack>
#include <cmath>
#include <set>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
const int INF = 0x3f3f3f3f;
const int maxn = 510;
int g[maxn][maxn], linker[maxn], lx[maxn], ly[maxn];
int slack[maxn], nx, ny, t, n, m;
bool visx[maxn], visy[maxn];
bool dfs(int x)
{
visx[x] = 1;
for(int y = 0; y < ny; y++){
if(visy[y]) continue;
int tmp = lx[x] + ly[y] - g[x][y];
if(tmp == 0){
visy[y] = 1;
if(linker[y] == -1 || dfs(linker[y])){
linker[y] = x;
return 1;
}
}
else if(slack[y] > tmp) slack[y] = tmp;
}
return false;
}
int KM()
{
memset(linker, -1, sizeof(linker));
memset(ly, 0, sizeof(ly));
for(int i = 0; i < nx; i++)
{
lx[i] = -INF;
for(int j = 0; j < ny; j++)
if(g[i][j] > lx[i]) lx[i] = g[i][j];
}
for(int x = 0; x < nx; x++){
for(int i = 0; i < ny; i++)
slack[i] = INF;
while(true)
{
memset(visx, false, sizeof(visx));
memset(visy, false, sizeof(visy));
if(dfs(x)) break;
int d = INF;
for(int i = 0; i < ny; i++)
if(!visy[i] && d > slack[i])
d = slack[i];
for(int i = 0; i < nx; i++)
if(visx[i]) lx[i] -= d;
for(int i = 0; i < ny; i++)
if(visy[i]) ly[i] += d;
else slack[i] -= d;
}
}
int res = 0;
for(int i = 0; i < ny; i++)
if(linker[i] != -1)
res += g[linker[i]][i];
return res;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &n, &m);
for(int i = 0; i <= n; i++)
for(int j = 0; j <= n; j++)
g[i][j] = -INF;
for(int i = 0; i < m; i++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if(g[a - 1][b - 1]) g[a - 1][b - 1] = max(g[a - 1][b - 1], -c);
else g[a - 1][b - 1] = -c;
}
nx = ny = n;
printf("%d\n", -KM());
}
return 0;
}
边栏推荐
猜你喜欢

SMILES的基本规则

最详细整理STL之vector基础

Unity analog flashlight light source detector, AI attack range detection area, object detection in visual cone, fan-shaped area detection, circular area detection, cone area detection

What noteworthy technologies of gold: the importance of fund management

C端添加Traceid的最终的方案

一行代碼可以做什麼?

Some shaders in AB package do not trigger the callback of ipreprocessshaders

NS32F103VBT6软硬件替代STM32F103VBT6

Fanuc robot carries out all backup, image backup and specific operations of loading backup files (picture and text)
![[parallel and distributed computing] 10B_ MapReduce GFS Implementation](/img/f9/3ce3c129d08f4e291f87217aae8fe2.png)
[parallel and distributed computing] 10B_ MapReduce GFS Implementation
随机推荐
[专利与论文-20]:江苏省南京市2022年电子信息申报操作指南
LVS+Keepalived高可用群集实战部署
[Patents and papers-19]: Notice on electronic information application of Nanjing City, Jiangsu Province in 2022 (medium and advanced)
Intersection du vecteur et du plan
Vector expansion mechanism of STL
Intersection of vector and plane
FANUC机器人进行全部备份和镜像备份以及加载备份文件的具体操作(图文)
Welcome to the markdown editor
Mysql database - index
What is more advantageous than domestic spot silver?
JVM的类加载过程
About n before variables in SQL server and other usage analysis
高考后网上查询信息,注意防范没有 SSL证书的网站
idea 有这个类但是找不到的问题
欢迎使用Markdown编辑器
PLC功能块系列之气缸功能块(FB)
【owt】p2p Signaling Server 运行
集群二---LVS负载均衡群集DR模式
浅谈代码语言的魅力
What plug-ins are available for vscade?