POJ 2400 Supervisor, Supervisee(KM二分图最大权值匹配)题解
题意:n个老板n个员工,先给你n*n的数据,i行j列代表第i个老板第j喜欢的员工是谁,再给你n*n的数据,i行j列代表第i个员工第j喜欢的老板是谁,如果匹配到第k喜欢的人就会产生一个分数k-1。现在让你给老板和员工配对,希望得到的分数的平均数最少,并给出哪个老板匹配哪个员工,多种情况按字典序输出。
思路:题目中的input提示是错的...
这题就是km最大权值匹配的裸题,分数最小那就把权值变负,然后跑出最少的总分。因为n比较小,可以dfs求出所有情况。
代码:
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxn = + ;
const int MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
int nx, ny;
int g[maxn][maxn];
int linker[maxn], lx[maxn], ly[maxn];
int slack[maxn];
bool visx[maxn], visy[maxn];
bool dfs(int x){
visx[x] = true;
for(int y = ; y < ny; y++){
if(visy[y]) continue;
int tmp = lx[x] + ly[y] - g[x][y];
if(tmp == ){
visy[y] = true;
if(linker[y] == - || dfs(linker[y])){
linker[y] = x;
return true;
}
}
else if(slack[y] > tmp){
slack[y] = tmp;
}
}
return false;
}
int km(){
memset(linker, -, sizeof(linker));
memset(ly, , sizeof(ly));
for(int i = ; i < nx; i++){
lx[i] = -INF;
for(int j = ; j < ny; j++){
if(g[i][j] > lx[i]){
lx[i] = g[i][j];
}
}
}
for(int x = ; x < nx; x++){
for(int i = ; 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 = ; i < ny; i++)
if(!visy[i] && d > slack[i])
d = slack[i];
for(int i = ; i < nx; i++)
if(visx[i])
lx[i] -= d;
for(int i = ; i < ny; i++){
if(visy[i]) ly[i] += d;
else slack[i] -= d;
}
}
}
int res = ;
for(int i = ; i < ny; i++){
if(linker[i] != -)
res += g[linker[i]][i];
}
return res;
}
int ans[maxn], vis[maxn];
int n, t, ret, num, ca = ;
void DFS(int u, int sco){
if(sco < ret) return;
if(u == n){
if(sco == ret){
printf("Best Pairing %d\n", num++);
for(int i = ; i < n; i++){
printf("Supervisor %d with Employee %d\n", i + , ans[i]);
}
}
return;
}
for(int i = ; i < n; i++){
if(vis[i]) continue;
vis[i] = ;
ans[u] = i + ;
DFS(u + , sco + g[u][i]);
vis[i] = ;
}
}
int main(){
scanf("%d", &t);
while(t--){
num = ;
scanf("%d", &n);
memset(g, , sizeof(g));
for(int i = ; i < n; i++){ //雇员i对老板s
for(int j = ; j < n; j++){
int s;
scanf("%d", &s);
s--;
g[s][i] += -j;
}
}
for(int i = ; i < n; i++){ //老板i对雇员s
for(int j = ; j < n; j++){
int s;
scanf("%d", &s);
s--;
g[i][s] += -j;
}
}
nx = ny = n;
ret = km();
double f = -ret / 2.0 / n;
if(ca != ) printf("\n");
printf("Data Set %d, Best average difference: %lf\n", ca++, f);
memset(vis, , sizeof(vis));
num = ;
DFS(, );
}
return ;
}
POJ 2400 Supervisor, Supervisee(KM二分图最大权值匹配)题解的更多相关文章
- HDU2255-奔小康赚大钱-二分图最大权值匹配-KM算法
二分图最大权值匹配问题.用KM算法. 最小权值的时候把权值设置成相反数 /*-------------------------------------------------------------- ...
- 二分图最大权值匹配 KM算法 模板
KM算法详解+模板 大佬讲的太好了!!!太好了!!! 转载自:http://www.cnblogs.com/wenruo/p/5264235.html KM算法用来求二分图最大权完美匹配. 本文配合该 ...
- POJ 2195 Going Home 【二分图最小权值匹配】
传送门:http://poj.org/problem?id=2195 Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submis ...
- POJ 2400 Supervisor, Supervisee(KM)
題目鏈接 題意 :N个部门和N个员工,每个部门要雇佣一个工人,部门对每个工人打分,从1~N,1表示很想要,N表示特别不想要,每个工人对部门打分,从1~N.1表示很想去这个部门,N表示特别不想去这个部门 ...
- HDU 2255 KM算法 二分图最大权值匹配
奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- 【模板】二分图最大权完美匹配KM算法
hdu2255模板题 KM是什么意思,详见百度百科. 总之知道它可以求二分图最大权完美匹配就可以了,时间复杂度为O(n^3). 给张图. 二分图有了边权,求最大匹配下的最大权值. 所以该怎么做呢?对啊 ...
- 【二分图最大权完美匹配】【KM算法】【转】
[文章详解出处]https://www.cnblogs.com/wenruo/p/5264235.html KM算法是用来求二分图最大权完美匹配的.[也就算之前的匈牙利算法求二分最大匹配的变种??] ...
- 【模板】二分图最大权完美匹配(KM算法)/洛谷P6577
题目链接 https://www.luogu.com.cn/problem/P6577 题目大意 给定一个二分图,其左右点的个数各为 \(n\),带权边数为 \(m\),保证存在完美匹配. 求一种完美 ...
- 奔小康赚大钱 HDU - 2255(最大权值匹配 KM板题)
奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
随机推荐
- Unity shader学习之渐变纹理
渐变纹理,及使用纹理来存储漫反射光照的结果,这种技术在游戏<军团要塞2>中流行起来,它也是由Valve公司(提出半兰伯特光照技术的公司)提出来的,他们使用这种技术来渲染游戏中具有插画风格的 ...
- RabbitMQ的使用场景
RabbitMQ的使用场景 1 大数据日志收集消息中间件应用场景 2 消息中间件在搜索系统DIH(伪实时)中的应用 伪实时的搜索系统: 后台系统:(作为生产者发送消息) ...
- Day8 面向对象
一.面向对象和面向过程 各位,我们现在如果要将大象放冰箱,用面向过程怎么实现呢? 1.把大象放到冰箱里 第一步:把冰箱门打开 第二步:把大象放进去 第三步:把门关上 def open_fridge_d ...
- Lua用一维数组存储一个n阶方阵,输出这个方阵的正对角线上的数的和与反对角线上的数的和的差的绝对值。
arr = {, , , , , , , , -} function diagonalDifference(arr) dimesion = math.sqrt(#arr) arr1 = {} sum1 ...
- Spark核心RDD:combineByKey函数详解
https://blog.csdn.net/jiangpeng59/article/details/52538254 为什么单独讲解combineByKey? 因为combineByKey是Spark ...
- 20155228 获取技能的成功经验和关于C语言学习的调查
内容提要 你有什么技能比大多人(超过90%以上)更好?针对这个技能的获取你有什么成功的经验?与老师博客中的学习经验有什么共通之处? 有关C语言学习的调查 你是怎么学习C语言的?(作业,实验,教材,其他 ...
- Jersey入门——对Json的支持
Jersey rest接口对POJO的支持如下: package com.coshaho.learn.jersey; import java.net.URI; import javax.ws.rs.C ...
- Linux基础命令---apwatch
arpwatch arpwatch指令可以监听网络设备和ip地址的对应关系,将发现的信息发送到系统日志“/var/log/message”. 此命令的适用范围:RedHat.RHEL.Ubu ...
- centos6.8安装DB2 10.5
1.把tar拷贝到/opt下面,用root账户,安装软件包 cd /opt tar -zxvf v9.5fp3b_linuxx64_server.tar.gz (64位) cd server ./db ...
- API gateway 之 kong 安装
kong安装: https://getkong.org/install/centos/ 下载指定版本rpm: wget https://bintray.com/kong/kong-community- ...