标签:key sni aced through 最小 else and fwrite sam
【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 2538 | Accepted: 719 |
Description
Input
Output
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
题目大意就是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;
}
【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)
标签:key sni aced through 最小 else and fwrite sam
原文地址:http://www.cnblogs.com/jhcelue/p/7255362.html