题意:有n个主管和n个职工,每个主管对职工有不同的喜好程度,职工也是,最喜欢的为0(每行第一个),后面的依次+1,求最优搭配,输出方案
思路:跑一下最小费最大流,然后用dfs搜索最小费的方案,数据不是很大
PS:输入数据有误,应该先是每个职工的喜好,再是主管的喜好
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<list>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#include<numeric>
#include<functional>
using namespace std;
typedef long long ll;
const int maxn = 35;
struct edge
{
int to,cf,w,rev;
};
int d[maxn],fa[maxn],inq[maxn],pr[maxn];
vector<struct edge> v[maxn];
int ans,n,vis[maxn],num,line[maxn][maxn];
void init(int x)
{
for(int i = 0; i <= x; i++)
v[i].clear();
}
void add(int from,int to,int cap,int cost)
{
v[from].push_back((edge){to,cap,cost,v[to].size()});
v[to].push_back((edge){from,0,-cost,v[from].size()-1});
}
int mincost(int s,int t)
{
queue<int> q;
while(!q.empty())
q.pop();
int c,f;
c = f = 0;
while(1)
{
memset(fa,-1,sizeof fa);
memset(d,0x3f,sizeof d);
d[s] = 0;
memset(inq,0,sizeof inq);
q.push(s);
while(!q.empty())
{
int x = q.front();q.pop();
inq[x] = 0;
for(int i = 0; i < v[x].size(); i++)
{
edge e = v[x][i];
int y = e.to;
if(e.cf && d[y] > d[x] + e.w)
{
d[y] = d[x] + e.w;
fa[y] = x;
pr[y] = i;
if(!inq[y])
{
inq[y] = 1;
q.push(y);
}
}
}
}
if(d[t] == 0x3f3f3f3f)
break;
int gen = 0x3f3f3f3f;
for(int a = t; a != s; a = fa[a])
gen = min(gen,v[fa[a]][pr[a]].cf);
for(int a = t; a != s; a = fa[a])
{
edge &e = v[fa[a]][pr[a]];
e.cf -= gen;
v[a][e.rev].cf += gen;
}
f += gen;
c += gen * d[t];
}
return c;//f 最大流,c最小费用
}
void dfs(int x,int sum)
{
if(sum > ans)
return;
if(x > n)
{
if(sum < ans)
return;
printf("Best Pairing %d\n",num++);
for(int i = 1; i <= n; i++)
printf("Supervisor %d with Employee %d\n",i,vis[i]-n);
return;
}
for(int i = n+1; i <= 2*n; i++)
{
if(!vis[i])
{
vis[i] = 1;
vis[x] = i;
dfs(x+1,sum+line[x][i]);
vis[i] = 0;
}
}
}
int main(void)
{
int T,i,j,k,kase = 1;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init(2*n+1);
memset(line,0,sizeof line);
for(i = 1; i <= n; i++)
{
for(j = 1; j <= n; j++)
{
scanf("%d",&k);
line[k][i+n] += j-1;
}
}
for(i = 1; i <= n; i++)
{
for(j = 1; j <= n; j++)
{
scanf("%d",&k);
line[i][k+n] += j-1;
}
}
for(i = 1; i <= n; i++)
{
for(j = n+1; j <= 2*n; j++)
add(i,j,1,line[i][j]);
}
for(i = 1; i <= n; i++)
add(0,i,1,0);
for(i = n+1; i <= 2*n; i++)
add(i,2*n+1,1,0);
ans = mincost(0,2*n+1);
printf("Data Set %d, Best average difference: %f\n",kase++,ans/(2.0*n));
num = 1;
memset(vis,0,sizeof vis);
dfs(1,0);
putchar('\n');
}
return 0;
}