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 ...
随机推荐
- java中JDBC连接Oracle数据库
package com.xxxx.lunwen.test;import java.sql.*;public class DBUtil { static { try { // 加载Oracle驱动程序 ...
- Some Useful Resources for the Future Usage
并发编程 http://ifeve.com/ 美国各州 http://114.xixik.com/usa-stats/ 美国各州邮编zip code -> https://www.douban. ...
- hdu4778 状态压缩
#include <iostream> #include <algorithm> #include <cstdio> #include <vector> ...
- hdu5489 树状数组+dp
2015-10-06 21:49:54 这题说的是个给了一个数组,然后删除任意起点的一个连续的L个数,然后求最长递增子序列<是递增,不是非递减>,用一个树状数组维护一下就ok了 #incl ...
- Spring源码阅读(五)
这一讲我们分析真正的bean实例创建方法——doCreateBean,源码分析如下 /** * Actually create the specified bean. Pre-creation pro ...
- flask 在模板中渲染错误消息
在模板中渲染错误消息 如果form.valicate_on_submit()返回False,说明验证没有通过,对于没有验证通过的字段,WTForms会把错误信息添加到表单类的errors属性中,这是一 ...
- 转:【专题十一】实现一个基于FTP协议的程序——文件上传下载器
引言: 在这个专题将为大家揭开下FTP这个协议的面纱,其实学习知识和生活中的例子都是很相通的,就拿这个专题来说,要了解FTP协议然后根据FTP协议实现一个文件下载器,就和和追MM是差不多的过程的,相信 ...
- JustOj 1936: 小明A+B
题目描述 小明今年3岁了, 现在他已经能够认识100以内的非负整数, 并且能够进行100以内的非负整数的加法计算. 对于大于等于100的整数, 小明仅保留该数的最后两位进行计算, 如果计算结果大于等于 ...
- [转载] 关于出现“使用 UNION、INTERSECT 或 EXCEPT 运算符合并的所有查询必须在其目标列表中有相同数目的表达式”错误的可能原因
1. 对于该问题确实存在UNION前后SELECT语句中的列数不同导致:2. 以下为个人遇到的一种可能:在项目开发中由于有张表是动态的,即有个基础表,其他的表按年月根据基础表来生成动态表,动态表结构和 ...
- scss简单用法