【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)

【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)

Supervisor, Supervisee

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 2538   Accepted: 719

Description

Suppose some supervisors each get to hire a new person for their department. There are N people to be placed in these N departments. Each supervisor interviews all N people, and ranks them according to how much she wants each of
them in her department (1 being "really want" and N being "really don‘t want"). In turn, each of the N candidates ranks each of the supervisors as to how much that person would like to work for that supervisor (again, 1 is "really want to work for him/her"
and N is "really don‘t want to work for him/her"). Given the scores that each supervisor has for each candidate, and the scores each candidate has for each manager, write a computer program to determine the "best match" of candidates to supervisors. The "best
match" is determined by finding the distribution that leads to the highest overall (i.e. sum of) satisfaction for all people. The closer a person is to her number one choice, the better. If everyone gets their number one choice, the average difference will
be 0.

Input

The first line of the input will contain a single integer greater than 0 specifying the number of test cases.

The next line will contain a single integer value N, 0 < N < 15, representing the number of supervisors (and the number of employees - there are N supervisors and N employees). The next N lines will be the preferences of each of the N supervisors. Each line
will contain N integer entries (1 through N for employees 1 through N), each separated by a space character, that represents the preferences of that supervisor from most preferred to least preferred. More specifically, the first entry on the line will represent
that supervisor‘s first choice, the second entry her second, and so on. The next N lines will be the preferences of the N employees, in the same format as the supervisors.

All lines of data in the input file will end with an empty line.

Output

For each test case, write the test case number (starting with 1) followed by the best average difference written to six digits of precision to the right of the decimal point. On the next line, show which best match it was (starting
with 1). On the next N lines, show each supervisor (starting with 1) followed by the employee with which she was matched (1 per line). NOTE: if there is more than one best match, matches should be listed in ascending permuted order (see sample output).

Separate each data set with an empty line.

Sample Input

2
7
1 2 3 4 5 6 7
2 1 3 4 5 6 7
3 1 2 4 5 6 7
4 1 2 3 5 6 7
5 1 2 3 4 6 7
6 1 2 3 4 5 7
7 1 2 3 4 5 6
1 2 3 4 5 6 7
2 1 3 4 5 6 7
3 1 2 4 5 6 7
4 1 2 3 5 6 7
5 1 2 3 4 6 7
6 1 2 3 4 5 7
7 1 2 3 4 5 6

2
1 2
2 1
1 2
1 2

Sample Output

Data Set 1, Best average difference: 0.000000
Best Pairing 1
Supervisor 1 with Employee 1
Supervisor 2 with Employee 2
Supervisor 3 with Employee 3
Supervisor 4 with Employee 4
Supervisor 5 with Employee 5
Supervisor 6 with Employee 6
Supervisor 7 with Employee 7

Data Set 2, Best average difference: 0.250000
Best Pairing 1
Supervisor 1 with Employee 1
Supervisor 2 with Employee 2

Source

field=source&key=Tehran+2003+Preliminary">Tehran 2003 Preliminary

题目大意就是n个上司与n名员工。每一个上司相应有想要搭配的员工。相同每一个员工有渴望搭配的上司。

输入第一行为N 之后n行为1~n号上司的期望 从左到右从最好到最差

相同之后n行是1~n号员工

匹配到最渴望的人值为0,否则从左到右一次加1

要求问平均期望的最小值,也就是最小值/2n

最小值用KM最小权匹配计算就可以,因为还要求输出解,有多解则输出多解。所以还要搜一下……

事实上数据非常少。找最小权匹配也用搜的也能够。

代码例如以下:

#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define fread() freopen("in.in","r",stdin)
#define fwrite() freopen("out.out","w",stdout)

using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 10000;
const double eps = 1e-8;

int mp[23][33];
int lx[33],ly[33],link[33],slack[33],next[33];
bool visx[33],visy[33],vis[33];
int n,ans,cnt;

bool cal(int x)
{
	visx[x] = 1;

	for(int y = 0; y < n; ++y)
	{
		if(visy[y]) continue;

		int t = lx[x]+ly[y]-mp[x][y];
		if(t == 0)
		{
			visy[y] = 1;
			if(link[y] == -1 || cal(link[y]))
			{
				link[y] = x;
				return 1;
			}
		}
		else slack[y] = min(slack[y],t);
	}
	return 0;
}

int KM()
{
	memset(link,-1,sizeof(link));

	for(int i = 0; i < n; ++i)
	{
		memset(slack,INF,sizeof(slack));
		while(1)
		{
			memset(visx,0,sizeof(visx));
			memset(visy,0,sizeof(visy));

			if(cal(i)) break;

			int d = INF;
			for(int i = 0; i < n; ++i)
				if(!visy[i]) d = min(d,slack[i]);

			for(int i = 0; i < n; ++i)
				if(visx[i]) lx[i] -= d;

			for(int i = 0; i < n; ++i)
				if(visy[i]) ly[i] += d;
				else slack[i] -= d;
		}
	}

	ans = 0;
	for(int i = 0; i < n; ++i)
		if(link[i] != -1) ans += mp[link[i]][i];

	return -ans;
}

void dfs(int id,int hs)
{
	if(hs < ans) return;
	if(id == n)
	{
		if(hs == ans)
		{
			printf("Best Pairing %d\n",++cnt);
			for(int i = 0; i < n; ++i)
			{
				printf("Supervisor %d with Employee %d\n",i+1,next[i]+1);
			}
		}
		return;
	}

	for(int i = 0; i < n; ++i)
	{
		if(vis[i]) continue;
		vis[i] = 1;
		next[id] = i;
		dfs(id+1,hs+mp[id][i]);
		vis[i] = 0;
	}
}

int main()
{
	int t,x;
	scanf("%d",&t);

	for(int z = 1; z <= t; ++z)
	{
		scanf("%d",&n);
		memset(ly,0,sizeof(ly));

		for(int i = 0; i < n; ++i)
			for(int j = 0; j < n; ++j)
			{
				scanf("%d",&x);
				mp[x-1][i] = -j;
			}

		for(int i = 0; i < n; ++i)
			for(int j = 0; j < n; ++j)
			{
				scanf("%d",&x);
				mp[i][x-1] -= j;
				if(j == 0) lx[i] = mp[i][x-1];
				else lx[i] = max(lx[i],mp[i][x-1]);
			}

		printf("Data Set %d, Best average difference: %.6f\n",z,KM()*0.5/n);

		cnt = 0;
		memset(vis,0,sizeof(vis));
		dfs(0,0);
		puts("");
	}

	return 0;
}
时间: 2024-08-10 02:09:42

【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)的相关文章

poj 2400 Supervisor, Supervisee KM求二分图+dfs输出所有解

题意: 有n个Supervisor和Supervisee,他们之间相互有一个评分,现在要求一个匹配,所有人的评分和最小,并输出使评分和最小的所有匹配方案. 分析: KM算法求二分图的最小权匹配,并用dfs输出所有方案. 代码: //poj 2400 //sep9 #include <iostream> using namespace std; const int maxN=16; char g[maxN][maxN]; int mx[maxN],my[maxN],hx[maxN],hy[max

ural 1076 KM求最小权匹配

贴模板~ KM算法引进了顶标函数,不断缩小这个顶标来让相等子图的可能范围扩大 #include<iostream> #include<cstring> //KM 复杂度O^3 using namespace std; const int N=200; int lx[N],ly[N];//顶标函数 int w[N][N];//图 bool vix[N],viy[N]; int linky[N];// int lack;//每次顶标函数扩大的增量 int n,m; bool find(

【POJ 2195】 Going Home(KM算法求最小权匹配)

[POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20303   Accepted: 10297 Description On a grid map there are n little men and n houses. In each unit time, every little man can move one unit ste

[ACM] POJ 3686 The Windy&#39;s (二分图最小权匹配,KM算法,特殊建图)

The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4158   Accepted: 1777 Description The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receivesN orders for toys. The man

POJ 3686 The Windy&#39;s【最小权匹配(神建图啊)】

大意:有n个任务m个机器,告诉你n*m的矩阵表示每个任务在每个机器上完成需要的时间 问所有任务完成的总时间最少?(比如第一个任务在第一分钟完成第二个任务在第二分钟完成   则总时间为1 + 2 = 3 分析: 该题自己做的时候没有思路 后来在网上搜题解,感觉建图真是太厉害了 假设最优情况下,个个任务需要的时间分别为a1, a2, a3, ……,an 那么总时间t = n * a1 + (n - 1) * a2 + ……+ 2 * an - 1 + an 也就是说只需要考虑系数就可以了 我们先假设

POJ 2195 Going Home(BFS+KM求最小权值)

Description: On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need to pay a $1 travel fee for every step

Fixed Partition Memory Management UVALive - 2238 建图很巧妙 km算法左右顶点个数不等模板以及需要注意的问题 求最小权匹配

/** 题目: Fixed Partition Memory Management UVALive - 2238 链接:https://vjudge.net/problem/UVALive-2238 题意:lv 思路:lrjP352. 来自lrj训练指南. n个程序作为左边结点, n*m个结点在右边:由于只要求n个程序在右边能找到的匹配点,km算法可以求解.修改nx,ny的值. if(f[i][j]==-1){ for(int k = 1; k <= n; k++) love[i][j*n+k-

poj 2195 Going Home 二分图最小权匹配KM算法

题意: 有n个人要回到n间房子里,每间房子只允许一个人,求n个人要走的最小距离和. 分析: 裸的二分图最小权匹配,KM搞之. 代码: //poj 2195 //sep9 #include <iostream> using namespace std; const int maxN=128; char g[maxN][maxN]; int mx[maxN],my[maxN],hx[maxN],hy[maxN]; int w[maxN][maxN]; int lx[maxN],ly[maxN],l

POJ 2195 二分图最小权匹配KM算法

本来是打算昨天晚上写的, 昨天网速渣的连CSDN都进不去,没办法 只能现在来写了 先写写对KM算法的理解,KM算法是对每个点设置一个顶标,只有当边长等于两边点的顶标之和的时候才进行增广,这样就能保证得到的一定是最大权匹配. 如果找不到匹配的时候就对交替路中X集合的顶标减少一个d Y集合的顶标增加一个d. 这样两个点都在交替路中的时候x[i]+y[i]的和不边 X在 Y不在的时候x[i]+y[i]减少,可能就会为图增加一对匹配. X不在Y在的时候x[i]+y[i]增加, 原来不在现在依然不在其中.